一、Nuitka介绍
打包思路
1.pyinstaller:简单,成功率高,但是能直接被解译。(优点:简单、成功率高;缺点:容易被破解看到源码)
2.cx\_freeze:不太追求性能,只是为了将代码编译。(优点:不被破解看到源码;缺点:比nuitka速度慢)
3.Nuitka:追求速度,且不被反编译直接看到源码。(优点:性能更快;缺点:成功率低,需要一些稳定的版本)
Nuitka介绍
官方手册:https://nuitka.net/user-documentation/
民间手册:https://jwndv2g391c.feishu.cn/wiki/Kqh1w1CeMis64HkLb4Lc6ODknob
增强工具:https://blog.csdn.net/loujiand/article/details/129051444
二、Nuitka打包环境准备
安装Nuitka包
pip install nuitka
版本很重要,有一些版本不稳定,按照通用打包命令运行时,如果有什么异常,可以考虑往前几个版本试试,当前我在用2.5.8
安装C编译环境
C编译环境概述
MinGW简介
MinGW (Minimalist GNU on Windows):实际上是将gcc(c/c++编译器)移植到了 Windows 平台下,并且包含了 Win32API ,因此可以将源代码编译为可在 Windows 中运行的可执行程序。而且还可以使用一些 Windows 不具备的,Linux平台下的开发工具。
- 编辑器:编辑修改和产生文件时所使用的软件。
- 编译器:编译是从源代码(通常为高级语言)到能直接被计算机执行的目标代码(通常为低级语言或机器语言)的翻译过程。
- 解释器:把高级编程语言一行一行直接转译运行。如果再执行那就再一行行翻译,不保留翻译后的可以运行的二进制代码。
Nuitka对MinGW的要求
- Windows 上的 MinGW64 C11 编译器,必须基于 gcc 11.2 或更高。如果没有找到可用的 C 编译器,它将被自动下载。
- 在所有其他平台上,至少使用 5.1 版的
gcc
编译器,低于此版本的g++
编译器至少使用 4.4 版作为替代。 - macOS X 和大多数 FreeBSD 架构上的
clang
编译器。 - 在 Windows 上,如果 Visual Studio 安装程序提供,可以使用 Windows 上的
clang-cl
编译器
所有版本的下载地址
https://github.com/brechtsanders/winlibs_mingw/releases/
简单说:
nuitka打包需要c环境,windows推荐使用mingw64来构建c环境,注意新的版本或许会有报错,Nuitka 对特定版本的winlibs-gcc
有严格依赖,它期望使用精确匹配的版本来进行相关的编译等操作。当前我在用12.2.0,打包成功率较高,完整的名称和下载地址是winlibs-x86_64-posix-seh-gcc-12.2.0-llvm-16.0.0-mingw-w64ucrt-10.0.0-r5.zip。
文件清单
x86_64-posix-sjlj
x86_64-posix-seh
x86_64-win32-sjlj
x86_64-win32-seh
i686-posix-sjlj
i686-posix-dwarf
i686-win32-sjlj
i686-win32-dwarf
释义1:
- DWARF:一种带调试信息(DWARF- 2(DW2)EH)的包, 所以比一般的包尺寸大,仅支持32位系统
- SJLJ:跨平台,支持32,64位系统,缺点是:运行速度稍慢,GCC不支持
- SEH: 调用系统机制处理异常,支持32,64位系统,缺点是:Gcc新版才支持
释义2:
- x86_64: 简称X64,64位操作系统
- i686: 32位操作系统 (i386的子集),差不多奔腾2(1997年5月)之后的CPU都是可以用的;
释义3:
- posix: 启用了C++ 11 多线程特性
- win32: 未启用 (从时间线上正在尝试也启用部分 Treading)
区别
- DWARF DWARF- 2(DW2)EH ,这需要使用DWARF-2(或DWARF-3)调试信息。 DW-2 EH可以导致可执行文件略显膨胀,因为大的调用堆栈解开表必须包含在可执行文件中。
- setjmp / longjmp(SJLJ)。基于SJLJ的EH比DW2 EH慢得多(在没有异常时会惩罚甚至正常执行),但是可以在没有使用GCC编译的代码或没有调用堆栈的代码上工作。
- 结构化异常处理(SEH) (Structured Exception Handling)Windows使用自己的异常
安装MinGW
通过Nuitka自动安装
1.在Python环境中安装nuitka,然后用其打包一个Python文件
pip install nuitka
nuitka main.py
2.执行后,信息如下,表示Nuitka询问是否安装它指定版本的MinGW64(版本是14.2.0posix-19.1.1-12.0.0-msvcrt-r2),无论是否同意安装,此时它会在提示的路径下创建一个同名文件夹。
(base) (ven1) PS D:\Code\PID> nuitka main.py
Nuitka-Options: Used command line options: main.py
Nuitka-Options:WARNING: You did not specify to follow or include anything but main program. Check options and make sure that is intended.
Nuitka: Starting Python compilation with Nuitka '2.5.7' on Python '3.11' commercial grade 'not installed'.
Nuitka: Completed Python level compilation and optimization.
Nuitka: Generating source code for C backend compiler.
Nuitka: Running data composer tool for optimal constant value handling.
Nuitka: Running C compilation via Scons.
Nuitka will use gcc from MinGW64 of winlibs to compile on Windows.
Is it OK to download and put it in 'C:\Users\ADMINI~1\AppData\Local\Nuitka\Nuitka\Cache\DOWNLO~1\gcc\x86_64\14.2.0posix-19.1.1-12.0.0-msvcrt-r2'.
Fully automatic, cached. Proceed and download? [Yes]/No :
3.如果输入yes后回车,就会下载该版本到提示的路径,然后自动解压出来(此时下载的压缩包可以手动删掉,不会影响),然后继续进行打包动作,然而,在它指定的这个版本下,报错了。
Nuitka: Downloading 'https://github.com/brechtsanders/winlibs_mingw/releases/download/14.2.0posix-19.1.1-12.0.0-msvcrt-r2/winlibs-x86_64-posix-seh-gcc-14.2.0-llvm-19.1.1-mingw-w64msvcrt-12.0.0-r2.zip'.
Nuitka: Extracting to 'C:\Users\ADMINI~1\AppData\Local\Nuitka\Nuitka\Cache\DOWNLO~1\gcc\x86_64\14.2.0posix-19.1.1-12.0.0-msvcrt-r2\mingw64\bin\gcc.exe'
Nuitka-Scons: Backend C compiler: gcc (gcc 14.2.0).
terminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error'
what(): filesystem error: Cannot convert character sequence: Illegal byte sequence
scons: *** [module.__main__.o] Error 3
terminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error'
what(): filesystem error: Cannot convert character sequence: Illegal byte sequence
scons: *** [__loader.o] Error 3
terminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error'
what(): filesystem error: Cannot convert character sequence: Illegal byte sequence
terminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error'
what(): filesystem error: Cannot convert character sequence: Illegal byte sequence
scons: *** [__constants.o] Error 3
scons: *** [__helpers.o] Error 3
FATAL: Failed unexpectedly in Scons C backend compilation.
Nuitka:WARNING: Complex topic! More information can be found at https://nuitka.net/info/scons-backend-failure.html
Nuitka-Reports: Compilation crash report written to file 'nuitka-crash-report.xml'.
4.难道是安装的有问题吗?通过nuitka --version
查看版本,发现安装的确实是它自己推荐的版本14.2.0posix-19.1.1-12.0.0-msvcrt-r2\mingw64\bin\gcc.exe (gcc 14.2.0)。也就是说,nuitka推荐的版本可能也会有问题,所以网络上很多教程都强调,只安装大家已经验证过没有问题的版本,不要追求最新版。
(base) (ven1) PS D:\Code\PID> nuitka --version
2.5.8
Commercial: None
Python: 3.11.5 (tags/v3.11.5:cce6ba9, Aug 24 2023, 14:38:34) [MSC v.1936 64 bit (AMD64)]
Flavor: CPython Official
Executable: D:\Code\打包测试\ven1\Scripts\python.exe
OS: Windows
Arch: x86_64
WindowsRelease: 10
Nuitka-Scons: Non downloaded winlibs-gcc 'C:\Users\Administrator\AppData\Local\Nuitka\Nuitka\Cache\downloads\gcc\x86_64\x86_64-14.2.0-release-posix-seh-ucrt-rt_v12-rev0\mingw64\bin\gcc.exe' is being ignored, Nuitka is very dependent on the precise one.
Version C compiler: ~\AppData\Local\Nuitka\Nuitka\Cache\DOWNLO~1\gcc\x86_64\14.2.0posix-19.1.1-12.0.0-msvcrt-r2\mingw64\bin\gcc.exe (gcc 14.2.0).
(base) (ven1) PS D:\Code\PID>
5.如果此时手动下载其他版本后(例如winlibs-x86_64-posix-seh-gcc-12.2.0-llvm-16.0.0-mingw-w64ucrt-10.0.0-r5)解压到指定的目录的同级目录下,无论加不加环境变量,还是会提示不可用,坚持要下载它指定的版本,此时的解决办法是,把你下载解压得到的MinGW文件夹放到它指定版本的文件夹目录下替换,此时再重新打包即可。可以继续查看下命令,就会发现文件夹还是14.2.0posix-19.1.1-12.0.0-msvcrt-r2\mingw64\bin\gcc.exe ,但是gcc的版本已经变成了 (gcc 12.2.0)。
(base) (ven1) PS D:\Code\PID> nuitka --version
2.5.8
Commercial: None
Python: 3.11.5 (tags/v3.11.5:cce6ba9, Aug 24 2023, 14:38:34) [MSC v.1936 64 bit (AMD64)]
Flavor: CPython Official
Executable: D:\Code\打包测试\ven1\Scripts\python.exe
OS: Windows
Arch: x86_64
WindowsRelease: 10
Version C compiler: ~\AppData\Local\Nuitka\Nuitka\Cache\DOWNLO~1\gcc\x86_64\14.2.0posix-19.1.1-12.0.0-msvcrt-r2\mingw64\bin\gcc.exe (gcc 12.2.0).
(base) (ven1) PS D:\Code\PID>
官方文档中说要设置一下环境变量,实际使用过程中发现不设置也可以正常使用
手动下载并配置环境变量
注意:如下方案,似乎在新版本的nuitka中并不生效,即便配置了环境变量或者使用--mingw参数,nuitka也会强制要求下载它的指定版本
下载地址:https://github.com/brechtsanders/winlibs_mingw/releases/
配置环境变量
打开控制面板,依次选择 系统和安全
、系统
、高级系统设置
、高级
、环境变量
- 在系统变量中新增一条 MINGW\_HOME=xxx\mingw64(xxx\mingw64 为解压路径)
编辑 系统变量 Path,在最后增加一条数据:%MINGW\_HOME%\bin
配置测试:win+R进入命令行模式,输入 gcc -v
可以在最后一行看到当前安装的版本
C:\Users\Administrator>gcc -v
Using built-in specs.
COLLECT_GCC=C:\Users\Administrator\AppData\Local\Nuitka\Nuitka\Cache\downloads\gcc\x86_64\14.2.0posix-19.1.1-12.0.0-msvcrt-r2\mingw64\bin\gcc.exe
COLLECT_LTO_WRAPPER=c:/users/administrator/appdata/local/nuitka/nuitka/cache/downloads/gcc/x86_64/14.2.0posix-19.1.1-12.0.0-msvcrt-r2/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/12.2.0/lto-wrapper.exe
OFFLOAD_TARGET_NAMES=nvptx-none
Target: x86_64-w64-mingw32
Configured with: ../configure --prefix=/R/winlibs64ucrt_stage/inst_gcc-12.2.0/share/gcc --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --enable-offload-targets=nvptx-none --with-pkgversion='MinGW-W64 x86_64-ucrt-posix-seh, built by Brecht Sanders' --with-tune=generic --enable-checking=release --enable-threads=posix --disable-sjlj-exceptions --disable-libunwind-exceptions --disable-serial-configure --disable-bootstrap --enable-host-shared --enable-plugin --disable-default-ssp --disable-rpath --disable-libstdcxx-debug --disable-version-specific-runtime-libs --with-stabs --disable-symvers --enable-languages=c,c++,fortran,lto,objc,obj-c++,jit --disable-gold --disable-nls --disable-stage1-checking --disable-win32-registry --disable-multilib --enable-ld --enable-libquadmath --enable-libada --enable-libssp --enable-libstdcxx --enable-lto --enable-fully-dynamic-string --enable-libgomp --enable-graphite --enable-mingw-wildcard --enable-libstdcxx-time --enable-libstdcxx-pch --with-mpc=/d/Prog/winlibs64ucrt_stage/custombuilt --with-mpfr=/d/Prog/winlibs64ucrt_stage/custombuilt --with-gmp=/d/Prog/winlibs64ucrt_stage/custombuilt --with-isl=/d/Prog/winlibs64ucrt_stage/custombuilt --enable-libstdcxx-backtrace --enable-install-libiberty --enable-__cxa_atexit --without-included-gettext --with-diagnostics-color=auto --enable-clocale=generic --with-libiconv --with-system-zlib --with-build-sysroot=/R/winlibs64ucrt_stage/gcc-12.2.0/build_mingw/mingw-w64 CFLAGS='-I/d/Prog/winlibs64ucrt_stage/custombuilt/include/libdl-win32 -Wno-int-conversion' CXXFLAGS=-Wno-int-conversion LDFLAGS='-pthread -Wl,--dynamicbase -Wl,--high-entropy-va -Wl,--nxcompat -Wl,--tsaware'
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 12.2.0 (MinGW-W64 x86_64-ucrt-posix-seh, built by Brecht Sanders)
(base) PS C:\Users\Administrator\AppData\Local\Nuitka\Nuitka\Cache\downloads\gcc\x86_64\14.2.0posix-19.1.1-12.0.0-msvcrt-r2\mingw64\bin>
常见问题
安装其他内容
nuitka main.py
首次打包,看起来会有2-3次的报错,其实是在提示下载一些依赖,自动联网下载到c盘个人用户\appdata\local\nuitka下,主要下载MinGW和depends(Dependency Walker)和ccache,后面两个只有几M体积
当然以上文件在国内大部分情况下直接下载都会是龟速或者直接下载报错,这里只需要在提示安装时选择yes,把下载地址和下载解压目录复制出来。科学上网手动下载对应文件并解压到命令行中提示的指定目录。
depends.exe
在第一次使用
--standalone
时,会提示安装Dependency Walker,nuitka需要使用这个工具来解析所有的依赖,从而决定拷贝哪些文件(dll,pyd)到exe目录。命令进行的过程中会自动检测该工具是否存在,没有的话会自动提示进行下载,网络没问题的时候直接回车或者输入yes就行了,但是如果网络状况不佳,就需要提前手动下载,否则命令会因此中断。具体步骤:手动下载和系统相匹配的版本(32位或64位),解压得到以下两个文件
depends.exe depends.dll
然后放置到对应的目录
x86的路径C:\Users\Administrator\AppData\Local\Nuitka\Nuitka\x86\
X64的路径
C:\Users\Administrator\AppData\Local\Nuitka\Nuitka\x86_64\
ps:我尝试过将工具放在path中,没有用,只能放在上面的路径里面
可以通过参数
--windows-dependency-tool=DEPENDENCY_TOOL
将其修改为其他依赖解析工具,比如pefile
,但是不建议修改。参数--windows-dependency-tool=DEPENDENCY_TOOL
仅限windows系统使用
三、Nuitka打包基础教程
简单测试—不导入任何模块
新建hello.py
def talk(message):
return "Talk " + message
先直接用python运行,看看有没有语法错误
python hello.py
然后进行打包构建
nuitka hello.py
命令结束后会生成一个exe,运行exe和执行上面第一条命令效果一样。
复杂测试—导入其他模块
为了测试模块引用,我们将上面的文件拆分成两部分
新建mdl.py
def talk(message):
return "Talk " + message
修改hello.py
from mdl import talk
def main():
print( talk("Hello World"))
if __name__ == "__main__":
main()
先直接用python运行,看看有没有语法错误
python hello.py
然后进行构建
nuitka hello.py
使用这条命令生成的exe可以正常运行。
但是要注意:
但如果将生成的exe拷贝到其他路径执行,将会执行失败,提示找不到mdl模块,这是因为使用上述命令生成的exe里面是并不包含上面的mdl模块,于是在执行该exe的时候,它会尝试去调用mdl.py,如果找不到mdl.py,当然就会提示找不到模块,这和py文件的执行原理是一样的。
exe同级目录下面会有一个python3x.dll文件,执行exe文件时,如果需要调用外部模块,需要这个文件的支持。
关于python3x.dll:
python3x.dll是与版本相对应的,如果是python3.8.3,那么就是python38.dll。实际上,这个文件和python安装目录下面的python3x.dll是同一个文件(的拷贝)。python3x.dll相当于一个运行时(runtime),类似于javac,或者微软的framwork,python代码通过nuitka生成了二进制代码(exe或者pyd),但仍然通过python3x.d ll保留了python的特性,比如调用一个python模块
现在将整个目录拷贝到其他路径,可以发现exe能够正常执行,因为此时exe文件能够通过python3x.dll找到mdl.py。
如果不想借助python3x.dll去调用模块,就要将这个模块打包进exe
nuitka --follow-import-to=mdl hello.py
再次将生成的exe单独拷贝到其他地方执行,可以看到能够正常运行,此时不再需要拷贝python3x.dll和其他任何的文件。
正式使用
常用参数
上面的测试过程,只是为了让你了解,默认的打包方式下,是需要注意依赖问题的,而我们一般都会打包成单文件形式。
这里给出一个常用的打包方式,可以根据自己的需要进行修改:
# windows下经常用的命令(单个文件+打包环境+关闭控制台+管理员权限+定义logo+清理过程文件+显示打包进度+显示内存占用+定义名称+定义版本+定义说明),注意最后的 main.py要根据实际情况修改
nuitka --onefile --standalone --windows-disable-console --windows-uac-admin --windows-icon-from-ico=我的logo.ico –remove-output --mingw64 --show-progress --show-memory --windows-product-name=上位机 --windows-product-version=1.0.0.2 --windows-file-description=一个软件的说明 out main.py
GUI工具
这种命令行参数,对于用户来说并不友好,所以有热心网友开发了GUI工具(html网页的形式),可以一键式配置,推荐使用:
视频介绍:https://www.bilibili.com/video/BV1JEsTe3EC4/
在线网站: nuitka-commander.github.io
项目主页: https://github.com/Nuitka-commander/nuitka-commander
HTML下载: https://github.com/Nuitka-Commander/nuitka-commander.github.io/releases/latest
在线使用:https://nuitka-commander.github.io/
此类GUI工具有挺多,例如还有:
https://github.com/271374667/NuitkaGUI
通用选项
- –-standalone 使得打包结果与本地的Python环境无关,可以发给没安装Python的电脑使用。
- –-onefile 使得打包结果为一个可执行的exe,而不是一个文件夹。
--onefile
选项下打出来的包本身就具备可移植性,因此不需要额外加上 --standalone
。
- –-remove-output 在打包结束后,清理打包过程中生成的临时文件。
- –-enable-plugin= 启用插件,等号后跟插件名。在要打包的Python代码使用了一些特殊的包时,需要启用插件,Nuitka才能够正确打包。如:如在代码中使用了PySide6,就需要加上
--enable-plugin=pyside6
。具体的插件列表可以使用nuitka --plugin-list
来查看。 - -–windows-disable-console 在运行打包后的程序时,不会弹出控制台,而是直接运行GUI程序。
-–windows-icon-from-ico= 为打包后的可执行文件添加图标,等号后跟图标文件路径。
值得注意的是,图标的格式也可以不是.ico,只需要安装过imageio包,Nuitka便可以自动将图片转换为.ico格式。
修复选项
打包程序往往并不是一次就能够打包成功的,常常会出现分析不出一部分的引用关系,忽略了一些数据文件等等情况。在这些情况下,我们需要根据运行程序后显示的报错信息,使用下面的选项来打出正确的包。
- –-include-package-data= 包含给定软件包名称中的数据文件,等号后软件包名称。有的时候Nuitka并不能正确分析出一些Python软件包所需要使用的数据文件,在运行程序时提示FileNotFoundError等错误,此时就需要使用该选项。如:
--include-package-data=ultralytics
- –-include-data-files= 按文件名包含数据文件,等号后的格式为<SRC=DEST>。SRC指的是文件夹的路径,DEST指的是文件夹相对于打包结果的路径,其中DEST只能使用相对路径。如:
--include-data-files=/Users/admin/Downloads/yolov5n.pt=./yolov5n.pt
- –-include-data-dir= 包含文件夹中的数据文件,等号后的格式为<SRC=DEST>。使用方法与
--include-data-files=
相同。
其他选项
参数--mingw64
实际上 --mingw64
与--msvc=MSVC
是一对孪生参数,这两个参数二选一,用于指定编译器,如果当前环境既安装了mingw64,又安装了msvc,可以使用该参数选择兼容性最好的编译器,建议使用mingw64。如果不存在上面两种编译器都存在的情况,就不需要显式设置这个参数,默认会调用系统中能用的编译器。
参数plugin control
这部分参数用于设置对某些第三方库或者python功能进行支持,在使用--standalone
时才会用到
如果程序中使用了pyqt或者pyside,那么
--plugin-enable=qt-plugins
如果程序中使用了numpy, scipy, pandas, matplotlib,那么
--plugin-enable=numpy
如果使用了这些库或功能,但是忘了进行插件参数设置,命令运行过程中会以红字今天提醒,按照提醒对命令进行调整即可
如果有多个插件需要启用
--plugin-enable=numpy --plugin-enable=qt-plugins --plugin-enable=tensorflow
①在使用pysimplegui(PySimpleGUI教程)时,需要在主代码中添加“import tkinter as tk”,并且设置--enable-plugins=tk-inter,这样可以让nuitka打包tkinter进你的代码中!
②在使用pyside6/pyqt6(PySide6教程)时,需要设置--enable-plugins=pyside6或者pyqt6。
可以使用 nuitka --plugin-list查看可用的插件
C:\Users\Administrator\Desktop\a>nuitka --plugin-list
The following optional standard plugins are available in Nuitka
--------------------------------------------------------------------------------
data-files
dill-compat
enum-compat
eventlet Required by the eventlet package
gevent Required by the gevent package
implicit-imports
multiprocessing Required by Python's multiprocessing module
numpy Required for numpy, scipy, pandas, matplotlib, etc.
pbr-compat
pmw-freezer Required by the Pmw package
pylint-warnings Support PyLint / PyDev linting source markers
qt-plugins Required by the PyQt and PySide packages
tensorflow Required by the tensorflow package
tk-inter Required by Python's Tk modules
torch Required by the torch / torchvision packages
参数Output choices
-o FILENAME
指定生成的可执行文件的文件名,但是生成pyd的时候无法使用,也就是在使用--module
的时候无法为pyd文件指定一个其他的文件名
--output-dir=DIRECTORY
指定打包好的文件存放的目录,默认为当前目录
--remove-output
使用nuitka进行打包的过程中,会生成一个用于build的中间临时目录,若可以使用该参数,命令完成后会自动删除build目录
--no-pyi-file
不生成pyi文件。pyi文件主要用于生成pyd文件时进行隐式import的检测
参数--show-progress 和--show-scons
用来显示详细打包过程,看得懂的话就加上吧,这部分还有几个参数,感兴趣的可以试试
--show-scons Operate Scons in non-quiet mode, showing the executed
commands. Defaults to off.
--show-progress Provide progress information and statistics. Defaults
to off.
--show-memory Provide memory information and statistics. Defaults to
off.
--show-modules Provide a final summary on included modules. Defaults
to off.
--verbose Output details of actions taken, esp. in
optimizations. Can become a lot. Defaults to off.
参数 --windows-disable-console
禁用终端窗口,当程序有一个图形化界面的时候经常用到,仅限windows系统
参数 --windows-icon=ICON_PATH
设定程序的图标,仅限windows系统
作者以简洁明了的语言,传达了深刻的思想和情感。
字里行间饱含人文关怀,温暖而有力。
建议多用口语化表达,拉近与读者距离。
案例丰富且贴合主题,论证逻辑环环相扣。
?文化类评语?
这篇文章如同一首动人的乐章,触动了读者内心深处的柔软。