Python 打包工具 Nuitka 入门指南

起因

由于最近用Python写了一个跟目标检测相关的小工具,如果直接分发代码文件一来是不够优雅,二来是对非计算机领域的用户来说不够友好,因此我萌生了给小工具打包的想法。

本来我以为这应该是一个轻松而愉快的过程,一行命令一个回车,然后去摸鱼20分钟,回来就可以收获到一个完美打好包的可执行文件。然而事情并没有我想象的那般顺利,甚至可以说是困难重重、荆棘丛生。不断地排查原因查找可能的错误,最后我花了两天的时间才终于打出了一个可以完美运行的可执行文件。

因此,我希望这一篇文章可以帮助到也正在为Python程序打包而苦恼的同学们。

环境

  • Python 3.9 (CPython)
  • Nuitka 1.5.3

常用选项

通用选项

  • –standalone 使得打包结果与本地的Python环境无关,即使得打包结果具备可移植性。
  • –onefile 使得打包结果为一个可执行文件,而不是一个文件夹。

小结:--onefile选项下打出来的包本身就具备可移植性,因此不需要额外加上 --standalone--onefile 打包结果像绿色软件,仅一个可执行文件;--standalone的打包结果像经过安装的软件,文件夹下包含运行所需要的文件和程序入口。

  • –remove-output 在打包结束后,清理打包过程中生成的临时文件。
  • –enable-plugin= 启用插件,等号后跟插件名。在要打包的Python代码使用了一些特殊的包时,需要启用插件,Nuitka才能够正确打包。如:如在代码中使用了PySide6,就需要加上--enable-plugin=pyside6。具体的插件列表可以使用nuitka --plugin-list来查看。
  • –disable-console 在运行打包后的程序时,不会弹出控制台,而是直接运行GUI程序。

手动修复选项

打包程序往往并不是一次就能够打包成功的,常常会出现分析不出一部分的引用关系,忽略了一些数据文件等等情况。在这些情况下,我们需要根据运行程序后显示的报错信息,使用下面的选项来打出正确的包。

  • –include-package-data= 包含给定软件包名称中的数据文件,等号后软件包名称。有的时候Nuitka并不能正确分析出一些Python软件包所需要使用的数据文件,在运行程序时提示FileNotFoundError等错误,此时就需要使用该选项。如:--include-package-data=ultralytics
  • –include-data-files= 按文件名包含数据文件,等号后的格式为。SRC指的是文件夹的路径,DEST指的是文件夹相对于打包结果的路径,其中DEST只能使用相对路径。如:--include-data-files=/Users/admin/Downloads/yolov5n.pt=./yolov5n.pt
  • –include-data-dir= 包含文件夹中的数据文件,等号后的格式为。使用方法与--include-data-files=相同。

Windows 独占选项

  • –windows-icon-from-ico= 为打包后的可执行文件添加图标,等号后跟图标文件路径。

值得注意的是,图标的格式也可以不是.ico,只需要安装过imageio包,Nuitka便可以自动将图片转换为.ico格式。

MacOS独占选项

  • –macos-create-app-bundle 创建应用程序(.app),而不是Unix可执行文件。(截至 Nuitka 1.5.3 还是实验性功能,可用性较低)
  • –macos-app-icon= 设置应用程序图标,等号后跟图标文件路径。同样,图标的格式也可以不是.icns,只需要安装过imageio包,Nuitka便可以自动将图片转换为.icns格式。

无需关注的选项

  • –follow-imports 作用是在打包过程中分析程序的引用关系,将Python主程序引用的包也一并打包。其实这件事本身很重要,毕竟在大多数情况下应该没人希望Nuitka只打包一个Python主程序文件。但是在 –standalone 和 –onefile 下,该选项是强制启用的,因此不需要额外加上。
  • –nofollow-import-to= 作用是在打包过程中忽略指定的Python软件包。作为入门指南,我不建议使用该选项,因为不当使用会引入一些难以解决的问题。

实用命令

python -m nuitka --help # 查看 Nuitka 帮助手册python -m nuitka --plugin-list # 查看 Nuitka 插件列表

举例

python -m nuitka --standalone --remove-output {your_python_program_name}.pypython -m nuitka --onefile --remove-output {your_python_program_name}.pypython -m nuitka --standalone --disable-console --enable-plugin=pyside6 --remove-output {your_python_GUI_program_name}.pypython -m nuitka --macos-create-app-bundle --disable-console --enable-plugin=pyside6 --remove-output {your_python_GUI_program_name}.py

注意事项

  1. 官方文档中提到,相对于直接使用nuitka命令,python -m nuitka是更好的选择。

Avoid running the nuitka binary, doing python -m nuitka will make a 100% sure you are using what you think you are. Using the wrong Python will make it give you SyntaxError for good code or ImportError for installed modules. That is happening, when you run Nuitka with Python2 on Python3 code and vice versa. By explicitly calling the same Python interpreter binary, you avoid that issue entirely.

  1. 用于执行Nuitka的Python解释器最好是CPython,即Python解释器的标准实现。使用Apple Python等Python解释器部分功能将受限。

It has to be CPython, Anaconda Python.

You need the standard Python implementation, called “CPython”, to execute Nuitka, because it is closely tied to implementation details of it.

优点

  1. 对动态链接库的分析相对准确
  2. 打包生成的软件占用空间较小

缺点

  1. 打包时间相对较长
  2. 有商业版本,需要收费

尾声

如果您觉得我写的还不错的话,希望您可以点个赞,点个收藏,您的支持对我来说非常重要!

我热烈欢迎您转载我的这篇文章,但要求您标明作者与出处。

如果文章中存在侵权之处,也请您告知我,我将及时修改。

参考

  1. Nuitka User Manual — Nuitka the Python Compiler documentation
  2. Nuitka Github 仓库