一、知乎入坑
写了一个小程序需要打包成exe,试了pyinstaller,打包出来超过1G,看知乎上Nuitka效果很好,决定尝试一下。
作者在使用时设定了非常多的限制条件,比如要用不带Anaconda、多个python版本的电脑,甚至还用上了虚拟机。
我是有Anaconda,决定尝试一下。
二、创建python≤3.8版本虚拟环境
因为Anaconda自带的base虚拟环境中python版本3.10,于是在Anaconda Prompt下面使用:
conda create -n gui python==3.7
创建一个名叫gui的虚拟环境,至于为什么python版本这么低,原因参看链接中Requirements部分
三、安装Nuitka所需的C编译器——Mingw64
从这里下载MinGW64,然后选择与Python匹配的64位或32位,一般选择x86_64-win32-sjlj。将其安装到C:\MinGW64或\MinGW64(与Nuitka运行相同的磁盘根目录)以自动找到它。具体安装步骤参考这里第1-3步
四、安装Nuitka
进入Anaconda Prompt里面,激活之前的虚拟环境:
conda activate gui
然后,再安装,如下三选一
pip install nuitka
# 或者
python -m pip install nuitka
# 或者
conda install -c conda-forge nuitka
五、创建一个hello.py程序
import time
def job():
print("hello")
if __name__ == "__main__":
while True:
job()
time.sleep(1)
加个延时是为了后面显示需要,我看很多示例程序都是只用一句print,打包好程序exe,点击运行一下就退出,根本看不到输出信息。
六、打包
利用Anaconda Prompt激活虚拟环境,切换到py程序所在文件夹,然后
nuitka --mingw64 --show-progress --show-scons hello.py
标题七、遇到的坑
第一个坑:
ModuleNotFoundError("No module named 'colorama'").
解决办法:
激活虚拟环境,pip install colorama
第二个坑:
Nuitka-Scons:INFO: CC 'C:\\mingw64\\bin\\gcc.exe' version check gives (8, 1, 0)
Nuitka-Scons:INFO: Initial CC: 'gcc'
Nuitka-Scons:INFO: Initial CCVERSION: (8, 1, 0)
Nuitka-Scons:INFO: Checking usability of 'C:\\mingw64\\bin\\gcc.exe' from 'gcc'
Nuitka-Scons:INFO: Too old gcc 'C:\\mingw64\\bin\\gcc.exe' ((8, 1, 0) < (11, 2)) ignored!
Nuitka-Scons:INFO: No usable C compiler, attempt fallback to winlibs gcc.
解决办法:
这个可以查看虚拟环境文件夹下/Lib/site-packages/nuitka/build/SconsCompilerSettings.py,其中checkWindowsCompilerFound函数说明Remove compiler of wrong arch or too old gcc and replace with downloaded winlibs gcc,移除旧的gcc编译器(在mingw64/bin下面的gcc.exe),下载winlibs gcc编译器,但是我下载半天都没下载下来,于是修改代码,将min_version版本设置为我们的gcc.exe版本,这样下面的判断gcc_version < min_version就不满足,就不需要换别的编译器。
if compiler_path is not None:
the_cc_name = os.path.basename(compiler_path)
if isGccName(the_cc_name):
gcc_version = myDetectVersion(env, compiler_path)
min_version = (8, 1, 0)
if gcc_version is not None and (
gcc_version < min_version
or "force-winlibs-gcc" in env.experimental_flags
):
scons_logger.info(
"Too old gcc %r (%r < %r) ignored!"
% (compiler_path, gcc_version, min_version)
)
# This also will trigger using it to use our own gcc in branch below.
compiler_path = None
env["CC"] = None
第三个坑:
import SCons.Script # pylint: disable=import-error
ModuleNotFoundError: No module named 'SCons'
解决方法:
这个模块导入是在/Lib/site-packages/nuitka/build/inline_copy/bin/scons.py中,同样使用激活虚拟环境,pip install Scons
第四个坑:
Nuitka-Scons:INFO: CC 'C:\\mingw64\\bin\\gcc.exe' version check gives (8, 1, 0)
Nuitka-Scons:INFO: Initial CC: 'gcc'
Nuitka-Scons:INFO: Initial CCVERSION: (8, 1, 0)
Nuitka-Scons:INFO: Checking usability of 'C:\\mingw64\\bin\\gcc.exe' from 'gcc'
Scons: Compiler used C:\mingw64\bin\gcc.exe
Nuitka-Scons:INFO: Backend C compiler: gcc (gcc).
Nuitka-Scons:INFO: LTO mode auto was resolved to mode: 'no' (not known to be supported).
Nuitka-Scons:INFO: Using C11 mode: True
Nuitka-Scons:INFO: Using resource mode: 'win_resource' (default for Windows).
Nuitka-Scons:INFO: Told to run compilation on 8 CPUs.
Nuitka-Scons:INFO: Checking if ccache is at 'C:\Users\CNXIGAO13\.conda\envs\gui\bin\ccache.exe' guessed path.
Nuitka-Scons:INFO: Checking if ccache is at 'C:\Users\CNXIGAO13\.conda\envs\gui\scripts\ccache.exe' guessed path.
Nuitka will make use of ccache to speed up repeated compilation.
Is it OK to download and put it in 'C:\Users\CNXIGAO13\AppData\Local\Nuitka\Nuitka\ccache\v3.7.12'.
No installer needed, cached, one time question.
Proceed and download? [Yes]/No
Yes
Nuitka:INFO: Downloading 'https://github.com/ccache/ccache/releases/download/v3.7.12/ccache-3.7.12-windows-32.zip'.
FATAL: Failed to download 'https://github.com/ccache/ccache/releases/download/v3.7.12/ccache-3.7.12-windows-32.zip'. Contents should manually be copied to 'C:\Users\CNXIGAO13\AppData\Local\Nuitka\Nuitka\ccache\v3.7.12\ccache-3.7.12-windows-32.zip'.
解决方法:
缺少ccache.exe,下载又失败,去github自己手动下载,按报错最后一句放到指定文件夹下(路径可能因人而异)
第五个坑:
打包好exe之后,点击运行报错,说缺少python37.dll
解决方法:
去虚拟环境文件夹下复制一个python37.dll放到hello.py程序所在文件夹,问题解决,这是一个比较简单的尝试,后面遇到复杂的问题会继续记录下来。