为什么学习nuitka,一个字"小"
使用nuitka打包的exe体积明显要比pyinstaller小很多,且启动速度要快个30%左右。
本着速度即是正义,因此没有特殊需求,就抛弃pyinstaller拥抱nuitka
注意:部分情况下nuitka可能打包比pyinstaller要大一些,请根据实际情况选择。
我尝试在对pyqt pyside系列的程序打包明显要比pyinstaller小,使用pyinstaller打包最少都需要个20-30m左右,但是使用nuitka就会小很多。一个只展示hello world的pyside6程序,都不使用upx压缩前提下nuitka大约17.6m,而pyinstaller高达30m
配置并安装mingw64
python安装nuitka
模块
pip install nuitka
安装完成首次打包先随便尝试:
nuitka --mingw64 --show-progress --show-memory --plugin-enable=pylint-warnings,upx,tk-inter --standalone --onefile --windows-icon-from-ico=b.ico --remove-output --disable-console ID_main.py
我这个命令是打包了一个tk程序,可根据实际修改。
正常情况会报两到三次错误,即提示所下载的文件版本等不对提示重新下载。
Usage: __main__.py [--module] [--run] [options] main_module.py
Options:
--help 显示此帮助消息并退出
--version 显示错误报告的版本信息和重要详细信息,然后退出。默认为关闭。
--module 创建一个可执行的扩展模块,而不是一个程序。默认为关闭。
--standalone 为输出启用独立模式。这允许您在不使用现有Python安装的情况下将创建的二进制文件传输到其他机器。这也意味着它将变得更大。它暗示了以下选项:"--follow imports"和"--python flag=no_site"。默认为关闭。
--onefile 在独立模式之上,启用onefile模式。这意味着不是一个文件夹,而是一个压缩的可执行文件被创建和使用。默认为关闭。
--python-debug 是否使用调试版本。Default使用您正在使用的来运行Nuitka,很可能是非调试版本。
--python-flag=FLAG 要使用的Python标志。默认值是您用来运行Nuitka的内容,这会强制执行特定的模式。这些选项也存在于标准Python可执行文件中。当前支持:"-S"(别名"no_site")、"static_hashes"(不使用哈希随机化)、"no_warnings"(不给出Python运行时警告)、"-O"(别名为"no_assels")、"no_docstring"(不使用文档字符串)、"-u"(别名为"unbuffered")和"-m"。默认为空。
--python-for-scons=PATH 如果使用Python3.3或Python3.4,请提供用于Scons的Python二进制文件的路径。否则,Nuitka可以使用您运行Nuitka的软件,也可以使用Windows注册表中的Python安装。在Windows上,需要Python 3.5或更高版本。在非Windows上,Python 2.6或2.7也可以。
--mingw64 #默认为已经安装的vs2017去编译,否则就按指定的比如mingw(官方建议)
--standalone 独立环境,这是必须的(否则拷给别人无法使用)
--windows-disable-console 没有CMD控制窗口
--output-dir=out 生成exe到out文件夹下面去
--show-progress 显示编译的进度,很直观
--show-memory 显示内存的占用
--enable-plugin=pyside6 打包pyside6模块的刚需
--plugin-enable=tk-inter 打包tkinter模块的刚需
--plugin-enable=numpy 打包numpy,pandas,matplotlib模块的刚需
--plugin-enable=torch 打包pytorch的刚需
--plugin-enable=tensorflow 打包tensorflow的刚需
--windows-icon-from-ico=你的.ico 软件的图标
--windows-company-name=Windows下软件公司信息
--windows-product-name=Windows下软件名称
--windows-file-version=Windows下软件的信息
--windows-product-version=Windows下软件的产品信息
--windows-file-description=Windows下软件的作用描述
--windows-uac-admin=Windows下用户可以使用管理员权限来安装
--linux-onefile-icon=Linux下的图标位置
--onefile 像pyinstaller打包成单个exe文件
--include-package=复制比如numpy,PyQt5 这些带文件夹的叫包或者轮子
--include-module=复制比如when.py 这些以.py结尾的叫模块
–-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=相同。
--follow-import-to=MODULE/PACKAGE 如果使用该模块,请遵循该模块;如果是一个包,请遵循整个包。可以多次给定。默认为空。
在多文件打包时会自动寻找其他导入文件,可作以下尝试
--include-package=PACKAGE 包括整个包裹。作为Python命名空间,例如"some_package.sub_package",然后Nuitka会找到它,并将它和在该磁盘位置下找到的所有模块包括在它创建的二进制或扩展模块中,并使其可供代码导入。为了避免不需要的子包,例如测试,您可以这样做"--nofollow import To=*.tests"。默认为空。
--include-module=MODULE 包括单个模块。将其作为Python命名空间,例如"some_package.some_module",然后Nuitka会找到它,并将其包含在它创建的二进制或扩展模块中,并使其可由代码导入。默认为空。
--include-plugin-directory=MODULE/PACKAGE 还包括在该目录中找到的代码,将它们视为一个主文件。覆盖所有其他包含选项。您应该更喜欢其他包含选项,这些选项以名称而不是文件名命名,这些选项通过在"sys.path"中查找内容。此选项仅适用于非常特殊的用例。可以多次给定。默认为空。
--include-plugin-files=PATTERN 包括在与图案匹配的文件中。覆盖所有其他跟随选项。可以多次给定。默认为空。
--prefer-source-code 对于已经编译的扩展模块,其中既有源文件又有扩展模块,通常使用扩展模块,但最好从可用的源代码编译模块以获得最佳性能。如果不需要,则有--no-preferred源代码来禁用有关它的警告。默认为关闭。
--follow-imports 下降到所有导入的模块中。在独立模式下默认为打开,否则为关闭。
--follow-import-to=MODULE/PACKAGE 如果使用该模块,请遵循该模块;如果是一个包,请遵循整个包。可以多次给定。默认为空。
--nofollow-import-to=MODULE/PACKAGE 即使使用该模块名称,也不要跟随该模块名称;或者,如果包名称在任何情况下覆盖整个包,则覆盖所有其他选项。可以多次给定。默认为空。
--nofollow-imports 根本不要进入任何导入的模块,覆盖所有其他包含选项,并且不适用于独立模式。默认为关闭。
--follow-stdlib 还可以从标准库中导入模块。这将大大增加编译时间,而且目前还没有经过很好的测试,有时也无法工作。默认为关闭。
--onefile-tempdir-spec=ONEFILE_TEMPDIR_SPEC 将其用作在一个文件模式下解压缩到的文件夹。默认为"%TEMP%/onefile_%PID%_%TIME%",即用户临时目录,并且是非静态的,它将被删除。例如,使用"%CACHE_DIR%%COMPANY%/%PRODUCT%/%VERSION%"这样的字符串,这是一个良好的静态缓存路径,因此不会删除。
--onefile-child-grace-time=GRACE_TIME_MS 当停止子项时,例如由于CTRL-C或关机等原因,Python代码会得到一个"KeyboardInterrupt",它可以处理该中断,例如刷新数据。这是以毫秒为单位的时间,在它以艰难的方式杀死孩子之前。单位为毫秒,默认为5000。
--include-package-data=PACKAGE 当停止子项时,例如由于CTRL-C或关机等原因,Python代码会得到一个"KeyboardInterrupt",它可以处理该中断,例如刷新数据。这是以毫秒为单位的时间,在它以艰难的方式杀死孩子之前。单位为毫秒,默认为5000。
--include-data-files=DESC 在分发中按文件名包括数据文件。允许的形式有很多。使用"--include data files=/path/to/file/*.txt=folder_name/some.txt",它将复制单个文件,如果是多个文件,则会抱怨。使用"--include data files=/path/to/files/*.txt=folder_name/",它会将所有匹配的文件放入该文件夹。对于递归复制,有一个具有3个值的表单"--include data files=/path/to/scan=folder_name=**/*.txt",将保留目录结构。默认为空。
--include-data-dir=DIRECTORY 在分发中包括完整目录中的数据文件。这是递归的。如果您想要非递归包含,请使用模式检查"--include data files"。一个例子是整个目录的"--include data dir=/path/some_dir=data/some_dir"(用于纯拷贝)。所有文件都将被复制,如果要排除文件,则需要事先将其删除,或者使用"--noinclude data files"选项将其删除。默认为空。
--noinclude-data-files=PATTERN 不要包含与给定文件名模式匹配的数据文件。这是针对目标文件名,而不是源路径。因此,要忽略包数据中的文件模式,"package_name"应匹配为"package_name/*.txt"。或者,对于整个目录,只需使用"packagename"。默认为空。
--list-package-data=LIST_PACKAGE_DATA 输出为给定包名称找到的数据文件。未完成默认设置。
--noinclude-dlls=PATTERN 不包括与文件名模式匹配的DLL文件鉴于这是针对目标文件名,而不是源文件名路径。因此,忽略包含在软件包"package_name"应匹配为"软件包名称/someDLL.*"。默认为空。
--list-package-dlls=LIST_PACKAGE_DLLS 输出为给定程序包名称找到的DLL。未完成默认设置。
--warn-implicit-exceptions 对编译时检测到的隐式异常启用警告。
--warn-unusual-code 对编译时检测到的异常代码启用警告。
--assume-yes-for-downloads 如果需要,允许Nuitka下载外部代码,例如依赖walker、ccache,甚至Windows上的gcc。要禁用,请重定向来自nul设备的输入,例如"
--run 立即执行创建的二进制文件(或导入编译后的模块)。默认为关闭。
--debugger 在调试器内部执行,例如"gdb"或"lldb",以自动获取堆栈跟踪。默认为关闭。
--execute-with-pythonpath 使用"--run"立即执行创建的二进制文件或模块时,不要重置"PYTHONPATH"环境。当所有模块都成功包含在内时,您应该不再需要PYTHONPATH,而且绝对不需要独立模式。
--user-package-configuration-file=YAML_FILENAME 用户提供的带有包配置的Yaml文件。您可以包括DLL、删除膨胀、添加隐藏的依赖项。有关要使用的格式的完整说明,请参阅《用户手册》。可以多次给定。默认为空。
--full-compat 强制执行与CPython的绝对兼容性。甚至不允许与CPython行为发生微小偏差,例如,没有更好的回溯或异常消息,这些消息并非真正不兼容,只是不同或更糟。这仅用于测试,不应使用。
--file-reference-choice=MODE 选择"__file__"的值。对于"运行时"(独立二进制模式和模块模式的默认值),创建的二进制文件和模块,使用其自身的位置来扣除"__file___"的值。包含的包假装在该位置下方的目录中。这允许您在展开中包含数据文件。如果您只是寻求加速,最好使用"原始"值,即将使用源文件位置的值。在"冻结"的情况下,会使用符号"<冻结模块名称>"。出于兼容性原因,"__file__"值将始终具有".py"后缀,而与实际值无关。
--module-name-choice=MODE 选择"__name__"和"__package__"的值。使用"运行时"(模块模式的默认值),创建的模块使用父包来推导"__package __"的数值,以完全兼容。值"original"(其他模式的默认值)允许进行更多的静态优化,但与通常可以加载到任何包中的模块不兼容。
--output-filename=FILENAME 指定应如何命名可执行文件。对于扩展模块没有选择,对于独立模式也没有选择,使用它将是一个错误。这可能包括需要存在的路径信息。在此平台上默认为""。执行
--output-dir=DIRECTORY 指定中间输出文件和最终输出文件的放置位置。DIRECTORY将填充构建文件夹、dist文件夹、二进制文件等。默认为当前目录。
--remove-output 生成模块或exe文件后删除生成目录。默认为关闭。
--no-pyi-file 不要为Nuitka创建的扩展模块创建".piy"文件。这用于检测隐式导入。默认为关闭。
--debug 在Nuitka中执行所有可能的自检以查找错误,不用于生产。默认为关闭。
--unstripped 在生成的对象文件中保留调试信息,以便更好地进行调试器交互。默认为关闭。
--profile 启用基于vmprof的花费时间分析。当前不工作。默认为关闭。
--internal-graph 创建优化过程内部的图形,不用于整个程序,而仅用于小型测试用例。默认为关闭。
--trace-execution 跟踪执行输出,在执行之前输出代码行。默认为关闭。
--recompile-c-only 这不是增量编译,而是仅用于Nuitka开发。获取现有文件,然后简单地将它们重新编译为C。允许编译经过编辑的C文件,以便快速调试对生成的源代码的更改,例如查看是否传递了代码、值输出等,默认为关闭。取决于编译Python源代码来确定应该查看哪些文件。
--xml=XML_FILENAME 将内部程序结构、优化结果以XML形式写入给定的文件名。
--generate-c-only 只生成C源代码,不将其编译为二进制或模块。这是为了调试和代码覆盖率分析,不会浪费CPU。默认为关闭。不要认为您可以直接使用此选项。
--experimental=FLAG 使用声明为"实验性"的功能。如果代码中没有实验特性,则可能没有任何效果。每个实验功能都使用秘密标签(检查源)。
--low-memory 通过分叉更少的C编译作业和使用使用更少内存的选项,尝试使用更少的内存。用于嵌入式机器。在内存不足的情况下使用此选项。默认为关闭。
--create-environment-from-report=CREATE_ENVIRONMENT_FROM_REPORT 在给定的报告文件的不存在路径中创建一个新的virtualenv,例如"--report=compilation-report.xml"。默认情况下未完成。
--clang 强制使用叮当声。在Windows上,这需要一个工作的Visual Studio版本才能搭载。默认为关闭。
--mingw64 在Windows上强制使用MinGW64。除非使用带有MinGW Python的MSYS2,否则默认为禁用。
--msvc=MSVC_VERSION 在Windows上强制使用特定的MSVC版本。允许的值是例如"14.3"(MSVC 2022)和其他MSVC版本号,指定"list"作为已安装编译器的列表,或使用"latest"。如果已安装,则默认为使用的最新MSVC,否则使用MinGW64。
--jobs=N 指定允许的并行C编译器作业数。默认为系统CPU计数。
--lto=choice 使用链接时间优化(MSVC、gcc、clang)。允许的值有"是"、"否"和"自动"(当已知有效时)。默认为"自动"。
--static-libpython=choice 使用Python的静态链接库。允许的值有"是"、"否"和"自动"(当已知有效时)。默认为"自动"。
--disable-cache=DISABLED_CACHES 禁用选定的缓存,为所有缓存指定"all"。当前允许的值为:"all"、"ccache"、"bytecode"、"dll dependencies"。可以多次给定,也可以使用逗号分隔的值。默认为无。
--clean-cache=CLEAN_CACHES 在执行之前清除给定的缓存,为所有缓存指定"all"。当前允许的值为:"all"、"ccache"、"bytecode"、"dll dependencies"。可以多次给定,也可以使用逗号分隔的值。默认为无。
--disable-bytecode-cache 不要重复使用作为字节码包含的模块的依赖性分析结果,特别是来自标准库的依赖性。与--disable-cache=字节码相同。
--disable-ccache 不要尝试使用ccache(gcc、clang等)或clcache(MSVC、clangcl)。与--disable-cache=cache相同。
--disable-dll-dependency-cache 禁用依赖项助行器缓存。将导致创建分发文件夹的时间更长,但可能会在怀疑缓存会导致错误的情况下使用。与--disable-cache=dll-依赖项相同。
--force-dll-dependency-cache-update 用于更新依赖项助行器缓存。将导致创建分发文件夹的时间更长,但可能会用于怀疑缓存会导致错误或已知需要更新的情况。
--pgo 通过首先为分析运行执行专用构建,然后使用结果反馈到C编译中,启用C级配置文件引导优化(PGO)。注意:这是实验性的,还不适用于Nuitka的独立模式。默认为关闭。
--pgo-args=PGO_ARGS 在配置文件引导优化的情况下要传递的参数。在PGO分析运行期间,这些文件被传递给特殊构建的可执行文件。默认为空。
--pgo-executable=PGO_EXECUTABLE 收集配置文件信息时要执行的命令。仅当您需要通过准备运行的脚本启动它时才使用此选项。默认使用创建的程序。
--report=REPORT_FILENAME XML输出文件中的报表模块、数据文件、编译、插件等详细信息。这对于问题报告也非常有用。例如,这些报告可以用于重新创建环境,使用"--从报告创建环境"很容易,但包含大量信息。默认为禁用。
--report-template=REPORT_DESC 通过模板进行报告。提供模板和输出文件名"template.rst.j2:output.rst"。对于内置模板,请查看《用户手册》中的内容。可以多次给定。默认值为空。
--quiet 禁用所有信息输出,但显示警告。默认为关闭。
--show-scons 使用详细信息运行C构建后端Scons,显示执行的命令和检测到的编译器。默认为关闭。
--no-progressbar 禁用进度条。默认为off.ted编译器。默认为关闭。
--show-progress 过时:提供进度信息和统计数据。禁用正常进度条。默认为关闭。
--show-memory 提供内存信息和统计信息。默认为关闭。
--show-modules 提供包含的模块和DLL的信息已过时:应改用"--report"文件。默认为关闭。
--show-modules-output=PATH 输出"--show modules"的位置应为文件名。默认为标准输出。
--verbose 输出所采取操作的详细信息,特别是在优化中。可以变得很多。默认为关闭。
--verbose-output=PATH 从"--verbose"输出的位置应该是一个文件名。默认为标准输出。
--disable-console 为Windows或macOS编译时,请禁用控制台窗口并创建GUI应用程序。默认为关闭。
--enable-console 为Windows或macOS编译时,请启用控制台窗口并创建控制台应用程序。这会禁用某些模块的提示,例如建议禁用它的"PySide"。默认值为true。
--force-stdout-spec=FORCE_STDOUT_SPEC 强制程序的标准输出到此位置。适用于禁用控制台的程序和使用Nuitka商业版Windows服务插件的程序。默认为非活动,例如使用"%PROGRAM%.out.txt",即程序附近的文件。
--force-stderr-spec=FORCE_STDERR_SPEC 强制程序的标准错误到此位置。适用于禁用控制台的程序和使用Nuitka商业版Windows服务插件的程序。默认为非活动,例如使用"%PROGRAM%.err.txt",即程序附近的文件。
--windows-icon-from-ico=ICON_PATH 添加可执行文件图标。对于不同的分辨率或内部有多个图标的文件,可以多次给定。在后面的情况下,您还可以使用#后缀,其中n是从1开始的整数索引,指定要包括的特定图标,以及要忽略的所有其他图标。
--windows-icon-from-exe=ICON_EXE_PATH 从此现有可执行文件复制可执行文件图标(仅限Windows)。
--onefile-windows-splash-screen-image=SPLASH_SCREEN_IMAGE 为Windows和onefile编译时,请在加载应用程序时显示此信息。默认为关闭。
--windows-uac-admin 请求Windows用户控制,以在执行时授予管理员权限。(仅限Windows)。默认为关闭。
--windows-uac-uiaccess 请求Windows用户控制,以强制仅从几个文件夹运行,远程桌面访问。(仅限Windows)。默认为关闭。
--macos-target-arch=MACOS_TARGET_ARCH 这应该在什么架构上运行。默认和限制是运行Python所允许的。默认值为"native",这是运行Python的体系结构。
--macos-create-app-bundle 为macOS编译时,请创建捆绑包,而不是纯二进制应用程序。目前是实验性的和不完整的。目前,这是解锁控制台禁用的唯一方法。默认为关闭。
--macos-app-icon=ICON_PATH 添加要使用的应用程序捆绑包的图标。只能给出一次。默认为Python图标(如果可用)。
--macos-signed-app-name=MACOS_SIGNED_APP_NAME 用于macOS签名的应用程序的名称。遵循"com.YourCompany.AppName"命名结果以获得最佳结果,因为这些结果必须是全局唯一的,并且可能会授予受保护的API访问权限。
--macos-app-name=MACOS_APP_NAME 要在macOS捆绑包信息中使用的产品的名称。默认为二进制文件的基本文件名。
--macos-app-mode=MODE 应用程序捆绑包的应用程序模式。当启动一个窗口,并希望出现在Docker中时,默认值"gui"非常适合。如果没有Window,应用程序就是一个"后台"应用程序。对于稍后显示的UI元素,"UI元素"介于两者之间。该应用程序不会出现在dock中,但在以后打开窗口时可以完全访问桌面。
--macos-sign-identity=MACOS_APP_VERSION 在macOS上登录时,默认情况下将使用特别标识,但通过此选项,您可以指定另一个要使用的标识。代码的签名现在在macOS上是强制性的,不能被禁用。如果未给出,则默认为"特别"。
--macos-sign-notarization 在签署公证时,使用苹果公司的正确TeamID身份,使用所需的运行时签名选项,以便可以接受。
--macos-app-version=MACOS_APP_VERSION 要在macOS捆绑包信息中使用的产品版本。如果未给定,则默认为"1.0"。
--macos-app-protected-resource=RESOURCE_DESC 请求访问macOS保护资源的权限,例如"NSMicrophoneUsageDescription:Microphone access for recording audio"。请求访问麦克风并为用户提供信息文本,说明为什么需要这样做。冒号之前是访问权限的操作系统标识符,然后是信息文本。法律价值可在https://developer.apple.com/documentation/bundleresources/information_property_list/p protected_resources和该选项可以指定多次。默认为空。
--linux-icon=ICON_PATH 为要使用的onefile二进制文件添加可执行图标。只能给出一次。默认为Python图标(如果可用)。
--company-name=COMPANY_NAME 要在版本信息中使用的公司的名称。默认为未使用。
--product-name=PRODUCT_NAME 要在版本信息中使用的产品的名称。默认为二进制文件的基本文件名。
--file-version=FILE_VERSION 要在版本信息中使用的文件版本。必须是最多4个数字的序列,例如1.0或1.0.0.0,不允许再有数字,不允许有字符串。默认为未使用。
--product-version=PRODUCT_VERSION 要在版本信息中使用的产品版本。与文件版本的规则相同。默认为未使用。
--file-description=FILE_DESCRIPTION 版本信息中使用的文件的说明。此时仅限Windows。默认为二进制文件名。
--copyright=COPYRIGHT_TEXT 版本信息中使用的版权。此时仅限Windows。默认为不存在。
--trademarks=TRADEMARK_TEXT 版本信息中使用的版权。此时仅限Windows。默认为不存在。
--enable-plugin=PLUGIN_NAME 已启用插件。必须是插件名称。使用"--plugin-list"查询完整列表并退出。默认为空。
--disable-plugin=PLUGIN_NAME 禁用的插件。必须是插件名称。使用"--plugin-list"查询完整列表并退出。大多数标准插件都不是禁用的好主意。默认为空。
--plugin-no-detection 插件可以检测它们是否可能被使用,您可以通过"--disable-plugin=plugin-that warnings"禁用警告,也可以使用此选项完全禁用该机制,这当然也会稍微加快编译速度,因为一旦您确定要使用哪些插件,此检测代码就会徒劳运行。默认为关闭。
--plugin-list 显示所有可用插件的列表并退出。默认为关闭。
--user-plugin=PATH 用户插件的文件名。可以多次给定。默认为空。
--show-source-changes 在编译之前显示对原始Python文件内容的源代码更改。主要用于开发插件。默认为False。
支持插件列表:
anti-bloat 修补愚蠢的从广泛使用的库模块中导入的源代码。
data-files 包括包配置文件指定的数据文件。
delvewheel 需要在独立模式下使用包来"支持"delewheel。
dill-compat "dill"包兼容性所需。
dll-files 根据程序包配置文件包括DLL。
enum-compat Python2和'enum'包需要。
eventlet 支持包含"eventlet"依赖项及其对"dns"包monkey补丁的需求。
gevent "gevent"包所需。
gi 支持GI包typelib依赖项。
glfw OpenGL和"glfw"软件包在独立模式下需要。
implicit-imports 根据包配置文件提供包的隐式导入。
kivy "kivy"包所需。
matplotlib "matplotlib"模块需要。
multiprocessing Python的"多处理"模块所需。
no-qt 禁用独立模式的所有Qt绑定。
options-nanny 根据软件包配置文件通知用户潜在的问题。
pbr-compat "pbr"包在独立模式下需要。
pkg-resources "pkg_resources"的解决方案。
pmw-freezer "Pmw"包所需。
pylint-warnings 支持PyLint/PyDev linting源标记。
pyqt5 PyQt5软件包所需。
pyqt6 PyQt6包在独立模式下所需。
pyside2 PySide2程序包所需。
pyside6 PySide6包在独立模式下需要。
pywebview "webview"包(PyPI上的pywebview)所需。
tk-inter Python的Tk模块所需。
trio "trio"套餐所需。
upx 使用UPX自动压缩创建的二进制文件。
使用tkinter QT pyside6等打包时需要注意加上选项,否则有可能导致打出来的包打不开
--plugin-enable=upx
--upx-binary=upx_dir
指定目录,upx选项到文件目录就可以,不用具体到文件--show-anti-bloat-changes 注释插件所做的更改。
--noinclude-setuptools-mode=NOINCLUDE_SETUPTOOLS_MODE 如果遇到"setuptools"或导入,该怎么办。这个包可能有很大的依赖性,绝对应该避免。还处理"setuptools_scm"。
--noinclude-pytest-mode=NOINCLUDE_PYTEST_MODE 如果遇到"pytest"导入,该怎么办。这个包可能有很大的依赖性,绝对应该避免。还处理"鼻子"进口。
--noinclude-unittest-mode=NOINCLUDE_UNITTEST_MODE 如果遇到单元测试导入,该怎么办。这个包可能有很大的依赖性,绝对应该避免。
--noinclude-IPython-mode=NOINCLUDE_IPYTHON_MODE 如果遇到IPython导入,该怎么办。这个包可能有很大的依赖性,绝对应该避免。
--noinclude-dask-mode=NOINCLUDE_DASK_MODE 如果遇到"dask"导入,该怎么办。这个包可能有很大的依赖性,绝对应该避免。
--noinclude-numba-mode=NOINCLUDE_NUMBA_MODE 如果遇到"numba"导入,该怎么办。这个包可能很大,有依赖项,并且目前不适用于单机版。这个包很大,有依赖关系,应该避免使用。
--noinclude-default-mode=NOINCLUDE_DEFAULT_MODE 这实际上为上述选项提供了默认的"警告"值,并可用于打开所有这些选项。
--noinclude-custom-mode=CUSTOM_CHOICES 如果遇到特定导入,该怎么办。格式是模块名称,可以也应该是顶级包,然后选择一个选项,"error"、"warning"、"nofollow",例如PyQt5:error。
想递归编译整个程序,而不仅仅是 作为主程序的单个文件,这样做:
python -m nuitka --follow-imports program.py
细粒度控件比可用控件多。请考虑 的输出。包括更少 模块到编译中,但使用普通的Python进行编译 将使编译速度更快。
--follow-imports``nuitka --help
如果您有一个包含动态加载文件的源目录,即 在正常导入语句之后通过递归找不到的一个 通过(这是推荐的方式),您可以 始终要求给定的目录也应包含在 可执行:PYTHONPATH
python -m nuitka --follow-imports --include-plugin-directory=plugin_dir program.py
如果您不执行任何动态导入,则只需在编译时设置即可。PYTHONPATH
仅当您进行 Nuitka 无法预测的调用时才使用,因为它们依赖于命令 线参数。Nuitka也警告了这些,并指出 选择。--include-plugin-directory``__import__()
生成的文件名将在Windows上,在其他平台上。program.exe program.bin
生成的二进制文件仍然依赖于CPython并使用C扩展 正在安装的模块。
如果您希望能够将其复制到另一台计算机,请使用并复制创建的目录和 执行 (Windows) 或 (其他) 平台)放在里面。--standalone``program.dist``program.exe``program
如果你想编译一个扩展模块,你所要做的就是 这:
python -m nuitka --module some_module.py
然后可以使用生成的文件代替 .some_module.so``some_module.py
选项和工作也一样,但包括 只有在导入名称后,模块才可导入。如果这些类型的导入不可见 Nuitka,例如动态创建,您可以使用或在这种情况下,但对于静态导入,它应该 不需要。
--follow-import-to``some_module``--include-module``--include-package
扩展模块永远不能包含其他扩展模块。你 必须创建一个轮子才能做到这一点。
生成的扩展模块只能加载到 CPython 中 相同的版本,不包括其他扩展模块。
如果您需要编译整个包并嵌入所有模块,那就是 同样可行,像这样使用 Nuitka:
python -m nuitka --module some_package --include-package=some_package
包内容的包含需要手动提供, 否则,包大多为空。您可以更具体地说明如果 你想要,并且只包含它的一部分,或排除它的一部分,例如 与您一起不会包括 代码中未使用的测试部分。
--nofollow-import-to='*.tests'
位于包内的数据文件不会被嵌入 过程中,您需要使用此方法自己复制它们。 或者,您可以使用Nuitka商业的文件嵌入。
为了分发到其他系统,有独立模式 生成一个文件夹,您可以为其指定 。–standalone
python -m nuitka --standalone program.py
在此模式下,默认遵循所有导入。您可以有选择地 通过明确表示排除模块,但是 然后,当尝试导入它时,将提出 程序运行时。这可能会导致不同的行为,但也可能导致 如果做得明智,可以缩短编译时间。--nofollow-import-to``ImportError
对于要包含的数据文件,请使用源为文件的选项 系统路径,但必须相对指定目标。对于独立您 也可以手动复制它们,但这可以进行额外的检查,并且 OneFile模式,无法手动复制。--include-data-files=
要复制目录中的部分或全部文件,请使用指定 shell 的选项 指示了文件的模式以及放置它们的子目录 通过尾部斜杠。--include-data-files=/etc/*.txt=etc/
要复制包含所有文件的整个文件夹,您可以使用 这将复制所有文件 包括潜在的子目录结构。你不能在这里过滤, 即,如果您只想要部分副本,请事先删除文件。--include-data-dir=/path/to/images=images
对于包数据,有更好的方法,使用它检测包的数据文件 自动并复制它们。它甚至接受外壳中的模式 风格。它使您无需自己查找软件包目录,并且 只要可用,就应该首选。--include-package-data
使用数据文件,您在很大程度上只能靠自己。努伊特卡跟踪一个 流行软件包需要,但它可能不完整。举 问题,如果你在这些东西中遇到什么。
当它起作用时,如果您愿意,可以使用onefile模式。
python -m nuitka --onefile program.py
这将创建一个二进制文件,该二进制文件在目标上提取自身, 在运行程序之前。但请注意,访问文件相对于 您的程序受到影响,请务必阅读 Onefile 部分: 也查找文件。
# Create a binary that unpacks into a temporary folder
python -m nuitka --onefile program.py
还有更多特定于平台的选项,例如与图标相关的选项, 初始屏幕和版本信息,请考虑输出以了解这些详细信息,并检查部分Tweaks_。
--help
对于解包,默认情况下使用唯一的用户临时路径, 然后删除,但是此默认值可以是 被正在使用然后使用缓存的路径规范覆盖 路径,避免重复解包,例如使用版本信息和用户特定的缓存目录。
--onefile-tempdir-spec="%TEMP%/onefile_%PID%_%TIME%"``--onefile-tempdir-spec="%CACHE_DIR%/%COMPANY%/%PRODUCT%/%VERSION"
例如,当Windows防火墙时,使用缓存的路径也是相关的 开始发挥作用,因为否则,二进制文件将有所不同 每次运行时一个。
目前,这些扩展令牌可用:
令 牌 | 这扩展到什么 | 例 |
---|---|---|
%TEMP% | User temporary file directory | C:Users…AppDataLocalsTemp |
%PID% | Process ID | 2772 |
%TIME% | Time in seconds since the epoch. | 1299852985 |
%PROGRAM% | Full program run-time filename of executable. | C:SomeWhereYourOnefile.exe |
%CACHE_DIR% | Cache directory for the user. | C:UsersSomeBodyAppDataLocal |
%COMPANY% | Value given as --company-name |
YourCompanyName |
%PRODUCT% | Value given as --product-name |
YourProductName |
%VERSION% | Combination of --file-version & --product-version |
3.0.0.0-1.0.0.0 |
%HOME% | Home directory for the user. | /home/somebody |
您有责任使所提供的路径独一无二,在 Windows正在运行的程序将被锁定,并且在使用固定 文件夹名称是可能的,在这种情况下可能会导致锁定问题, 程序重新启动的位置。
通常您需要使用或至少制作一个 路径唯一,这主要用于用例,例如 您希望事物位于您选择的位置或遵守您的命名 约定。
%TIME%``%PID%
如果您有 ,或驱动 为您的软件创建轮子,使用 Nuitka 是 非常容易。setup.py``setup.cfg``pyproject.toml
让我们从最常见的方法开始,您可以 - 当然,安装 Nuitka 后,只需执行目标而不是 .它需要所有 选项,并允许您指定更多特定于 努伊特卡。setuptools``bdist_nuitka``bdist_wheel
# For setup.py if not you't use other build systems:
setup(
...,
command_options={
'nuitka': {
# boolean option, e.g. if you cared for C compilation commands
'--show-scons': True,
# options without value, e.g. enforce using Clang
'--clang': None,
# options with single values, e.g. enable a plugin of Nuitka
'--enable-plugin': "pyside2",
# options with several values, e.g. avoiding including modules
'--nofollow-import-to' : ["*.tests", "*.distutils"],
}
},
)
# For setup.py with other build systems:
# The tuple nature of the arguments is required by the dark nature of
# "setuptools" and plugins to it, that insist on full compatibility,
# e.g. "setuptools_rust"
setup(
...,
command_options={
'nuitka': {
# boolean option, e.g. if you cared for C compilation commands
'--show-scons': ("setup.py", True),
# options without value, e.g. enforce using Clang
'--clang': ("setup.py", None),
# options with single values, e.g. enable a plugin of Nuitka
'--enable-plugin': ("setup.py", "pyside2"),
# options with several values, e.g. avoiding including modules
'--nofollow-import-to' : ("setup.py", ["*.tests", "*.distutils"]),
}
},
)
如果由于某种原因,您不能或不更改目标,则您 可以将其添加到您的 .setup.py
# For setup.py
setup(
...,
build_with_nuitka=True
)
要暂时禁用编译,您可以删除上面的行, 或将值编辑为 by 或从 环境变量(如果您愿意),例如 .这取决于你。
False``bool(os.environ.get("USE_NUITKA", "True"))
或者你可以把它放在你的setup.cfg
[metadata]
build_with_nuitka = True
最后但并非最不重要的一点是,Nuitka 也支持新的元,所以 当您已经有一个,简单的替换或添加这个 价值:build``pyproject.toml
[build-system]
requires = ["setuptools>=42", "wheel", "nuitka", "toml"]
build-backend = "nuitka.distutils.Build"
[nuitka]
# These are not recommended, but they make it obvious to have effect.
# boolean option, e.g. if you cared for C compilation commands, leading
# dashes are omitted
show-scons = true
# options with single values, e.g. enable a plugin of Nuitka
enable-plugin = pyside2
# options with several values, e.g. avoiding including modules, accepts
# list argument.
nofollow-import-to = ["*.tests", "*.distutils"]
对于上述绝对路径的要求,例如在 Linux 上也可以使用,请使用绝对路径 带有两个前导斜杠,例如 .
nuitka``C:\Users\...\Nuitka``//home/.../Nuitka
如果您有多个程序,则每个程序都应该是可执行的,在 过去,您必须多次编译,并部署所有这些。跟 独立模式,这当然意味着你相当浪费,因为 可以共享文件夹,但实际上并不支持 努伊特卡。
进入。有一个选项可以替换或 添加到给出的位置参数。并且可以给予多个 次。当多次给定时,Nuitka 将创建一个二进制文件 包含所有给定程序的代码,但共享模块用于 他们。因此,它们不必多次分发。Multidist``--main-path
让我们调用主路径和入口点的基本名称。的名称 这些当然是不同的。然后创建的二进制文件可以执行 任一入口点,并将对出现的情况做出反应 它。因此,如果以正确的方式执行(使用类似或OS API的内容,您可以控制此名称),或者通过重命名或复制 二进制或符号链接到它,然后你可以实现奇迹。sys.argv[0]``subprocess
这允许将非常不同的程序组合成一个。
此模式适用于独立、单文件和单纯加速。它确实如此 不适用于模块模式。
为了美观,您可以指定图标。在 Windows 上,您可以提供 图标文件、模板可执行文件或 PNG 文件。所有这些都将起作用 甚至可以组合:
# These create binaries with icons on Windows
python -m nuitka --onefile --windows-icon-from-ico=your-icon.png program.py
python -m nuitka --onefile --windows-icon-from-ico=your-icon.ico program.py
python -m nuitka --onefile --windows-icon-template-exe=your-icon.ico program.py
# These create application bundles with icons on macOS
python -m nuitka --macos-create-app-bundle --macos-app-icon=your-icon.png program.py
python -m nuitka --macos-create-app-bundle --macos-app-icon=your-icon.icns program.py
使用 Nuitka,您不必创建特定于平台的图标,但是 相反,它将即时转换例如.PNG,但也转换其他格式 在构建过程中。
macOS应用程序捆绑包的权限可以添加选项,–macOS应用程序保护资源,所有值都列在苹果的此页面上
示例值为–macos app protected resource=NSMicrophoneUsageDescription:用于请求访问麦克风的麦克风访问权限。在冒号之后,将给出描述性文本。
请注意,在描述部分可能使用空格的情况下,您需要为您的shell引用空格,以接通Nuitka,而不是将其解释为Nuitka参数。
在Windows上,控制台是由程序打开的,除非你这么说。Nuitka默认这样做,实际上只适用于终端程序或要求查看输出的程序。pythonw.exe和python.exe在这些方面有区别。这是通过选项–disable console在Nuitka中复制的。Nuitka建议您在使用PySide6(例如)和其他GUI包(例如wx)的情况下考虑这一点,但这将由您决定。在这种情况下,您知道您的程序是控制台应用程序,只需使用–enable控制台就可以从Nuitka中消除这些类型的输出。
pythonw.exe永远不适合与Nuitka一起使用,因为您看不到它的输出。
当程序启动缓慢时,启动屏幕非常有用。Onefile启动本身并不慢,但你的程序可能会慢,而且你无法真正知道使用的计算机会有多快,所以拥有它们可能是个好主意。幸运的是,有了Nuitka,它们很容易为Windows添加。
对于启动屏幕,您需要将其指定为PNG文件,然后确保在程序准备就绪时禁用启动屏幕,例如,已完成导入、准备好窗口、连接到数据库,并希望启动屏幕消失。在这里,我们使用项目语法将代码与创建相结合,编译如下:
# nuitka-project: --onefile
# nuitka-project: --onefile-windows-splash-screen-image={MAIN_DIRECTORY}/Splash-Screen.png
# Whatever this is obviously
print("Delaying startup by 10s...")
import time
time.sleep(10)
# Use this code to signal the splash screen removal.
if "NUITKA_ONEFILE_PARENT" in os.environ:
splash_filename = os.path.join(
tempfile.gettempdir(),
"onefile_%d_splash_feedback.tmp" % int(os.environ["NUITKA_ONEFILE_PARENT"]),
)
if os.path.exists(splash_filename):
os.unlink(splash_filename)
print("Done... splash should be gone.")
...
# Rest of your program goes here.
对于您的程序和Nuitka包装的分析,有可用的汇编报告。您还可以制作自定义报告,提供自己的模板,其中一些模板内置于Nuitka中。这些报告包含所有详细信息,例如,当试图导入模块但未找到时,您可以看到发生这种情况的位置。对于错误报告,非常建议提供报告。
在Windows上编译的二进制文件,默认设置为Nuitka,没有采取进一步的操作,可能会被一些AV供应商识别为恶意软件。这是可以避免的,但只有在Nuitka商业广告中,才有关于如何做到这一点的实际支持和指示,将其视为典型的商业需求。https://nuitka.net/doc/commercial.html
有时,C编译器会崩溃,说它们无法分配内存,或者某些输入被截断,或者类似的错误消息,很明显来自于内存。您可以在这里探索以下几个选项:
有一个专门的选项——低内存,这会影响Nuitka的决策,从而避免在编译过程中以增加编译时间为代价大量使用内存。
不要使用32位编译器,而是使用64位编译器。如果你在Windows上使用32位的Python,你肯定应该使用MSVC作为C编译器,而不是MinGW64。MSVC是一个交叉编译器,在该平台上可以使用比gcc更多的内存。如果你不在Windows上,那当然不是一个选项。同样使用64位Python也可以。
当您从活动安装进行编译时,很可能安装了许多可选的软件依赖项。一些软件,然后会导入这些软件,Nuitka也会编译它们。这些不仅可能只是麻烦制造者,它们还需要更多的内存,所以去掉它们。当然,在尝试编译之前,您必须检查您的程序是否具有所有所需的依赖项,否则编译后的程序将同样无法运行。
使用–lto=yes或–lto=no,您可以将C编译切换为只生成字节码,而不是直接生成汇编代码和机器代码,而是在最后进行整个程序优化。这将极大地改变内存使用情况,如果您的错误来自汇编程序,那么使用LTO绝对可以避免这种情况。
人们报告说,由于gcc的错误或内存使用而无法使用gcc编译的程序在Linux上可以使用clang。在Windows上,这仍然是一个选项,但它需要首先为自动下载的gcc实现,该gcc将包含它。由于众所周知,MSVC无论如何都更有效地节省内存,你应该去那里,如果你想使用Clang,MSVC中包含的支持。
在RAM不足的系统上,需要使用交换空间。用完它可能是一个原因,添加更多的交换空间或一个交换空间可能会解决这个问题,但要注意,当编译器来回交换时,这会使事情变得非常缓慢,所以请先考虑下一个技巧或最重要的技巧。
使用Nuitka的–jobs选项,它不会同时启动许多C编译器实例,每个实例都在争夺稀缺的RAM资源。通过选择一个值,只有一个C编译器实例将运行,并且在8核系统上,这将使内存量减少8倍,因此这是一个自然的选择。
如果您的脚本修改sys.path,例如插入与之相关的源代码目录,Nuitka将无法看到这些目录。但是,如果您将PYTHONPATH设置为结果值,它将能够编译它,并从这些路径中找到使用的模块。
私有代码的一个非常常见的模式是,它扫描某种插件目录,例如使用os.listdir,然后考虑Python文件名,然后打开一个文件并对其执行。这种方法适用于Python代码,但对于编译后的代码,您应该使用这种更干净的方法,它适用于纯Python代码,并且不太容易受到攻击。
# Using a package name, to locate the plugins. This is also a sane
# way to organize them into a directory.
scan_path = scan_package.__path__
for item in pkgutil.iter_modules(scan_path):
importlib.import_module(scan_package.__name__ + "." + item.name)
# You may want to do it recursively, but we don't do this here in
# this example. If you want to, handle that in this kind of branch.
if item.ispkg:
...
如果你的程序无法归档数据,可能会导致各种不同的行为,例如,一个包可能会抱怨它的版本不正确,因为version文件检查默认为未知。缺少图标文件或帮助文本,可能会引发奇怪的错误。
通常,不存在的文件的错误路径甚至是有缺陷的,并且会显示编程错误,如未绑定的局部变量。请仔细查看这些例外情况,记住这可能是原因。如果您的程序在没有独立程序的情况下运行,则可能是数据文件造成的。
表示缺少文件的最常见错误当然是带有文件名的未捕获FileNotFoundError。您应该弄清楚哪个包缺少文件,然后使用–include package data(最好)或–include data dir/–include数据文件来包含它们。
Nuitka有处理复制DLL的插件。对于NumPy、SciPy、Tkinter等。
这些需要特殊处理才能在其他系统上运行。手动复制它们是不够的,并且会出现奇怪的错误。有时不支持更新版本的软件包,特别是NumPy。在这种情况下,您将不得不提出一个问题,并使用旧的问题。
有些包裹是单一进口的,但对Nuitka来说,这意味着要包括1000多个包裹。Pandas的主要例子,它确实想插上并使用你能想象到的几乎所有东西。多个语法框架突出显示所有可以想象到的内容需要时间。
Nuitka将来必须学习有效的缓存来处理这个问题。现在,您将不得不处理这些文件的大量编译时间。
应该应用对抗依赖蠕变的一个主要武器,即反膨胀插件,它提供了有趣的功能,可以使用并阻止不必要的导入,并给出它们发生的错误。使用它,例如这样–noinclude pytest mode=nofollow–noinclude setuptools mode=nofollow,例如–noincclude custom mode=setuptools:error,使编译器为特定包出错。请确保检查其帮助输出。它可以用于您选择的每个模块,例如,还强制PyQt5被视为卸载以用于独立模式。
它还由一个配置文件anti-bloat.yml驱动,您可以为其提供帮助,从包中删除典型的膨胀。请随意增强它,并用它向努伊特卡制作公关。
正常工作的标准代码也可以工作,您应该参考os.path.dirname(file)或使用所有包,如pkgutil、pkg_resources、importlib.resources来定位独立二进制文件附近的数据文件。
您不应该使用当前目录os.getcwd,或者假设这是脚本目录,例如使用data/等路径。
如果你那样做了,那就不是一个好的代码。链接、到一个程序、从另一个目录启动等等都会以糟糕的方式失败。不要对程序启动的目录做出假设。
sys.argv[0]和主模块的__file__之间存在差异,这是由于使用引导到临时位置造成的。第一个将是原始可执行文件路径,第二个将是引导程序可执行文件解包到的临时或永久路径。数据文件将在后面的位置,原始环境文件将在前面的位置。
给定两个文件,一个您希望位于可执行文件附近,另一个您期望位于onefile二进制文件内,这样访问它们。
# This will find a file *near* your onefile.exe
open(os.path.join(os.path.dirname(sys.argv[0]), "user-provided-file.txt"))
# This will find a file *inside* your onefile.exe
open(os.path.join(os.path.dirname(__file__), "user-provided-file.txt"))
出于调试目的,请删除–disable控制台或使用选项–windows强制stdout规范和–windows强制标准错误规范,路径如上面针对–onefile tempdir规范所述。这些可以是相对于程序的,也可以是绝对的,因此您可以看到给定的输出。
有时人们会使用这种代码,对于PyPI上的包,我们通过动态地进行源代码补丁来处理。如果这是在您自己的代码中,以下是您可以执行的操作:
def binder(func, name):
result = types.FunctionType(func.__code__, func.__globals__, name=func.__name__, argdefs=func.__defaults__, closure=func.__closure__)
result = functools.update_wrapper(result, func)
result.__kwdefaults__ = func.__kwdefaults__
result.__name__ = name
return result
编译后的函数不能用于从创建未编译的函数,因此上面的代码将不起作用。但是,有一种专用的克隆方法,它是特定于它们的,所以请改用此方法。
def binder(func, name):
try:
result = func.clone()
except AttributeError:
result = types.FunctionType(func.__code__, func.__globals__, name=func.__name__, argdefs=func.__defaults__, closure=func.__closure__)
result = functools.update_wrapper(result, func)
result.__kwdefaults__ = func.__kwdefaults__
result.__name__ = name
return result
支持条件选项和使用预定义变量的选项,例如:
# Compilation mode, support OS specific.
# nuitka-project-if: {OS} in ("Windows", "Linux", "Darwin", "FreeBSD"):
# nuitka-project: --onefile
# nuitka-project-if: {OS} not in ("Windows", "Linux", "Darwin", "FreeBSD"):
# nuitka-project: --standalone
# The PySide2 plugin covers qt-plugins
# nuitka-project: --enable-plugin=pyside2
# nuitka-project: --include-qt-plugins=sensible,qml
注释必须是一行的开头,并且要使用缩进来结束一个条件块,就像Python中一样。除了上面演示的已使用的关键字之外,目前没有其他关键字。
你可以在那里放任意的Python表达式,如果你想访问包的版本信息,你可以简单地使用__import__(“module_name”)版本,如果需要启用或禁用某些Nuitka设置。Nuitka所做的唯一一件事使这不是Python表达式,那就是为预定义的变量集扩展{variable}:
包含支持变量的表:
Variable | What this Expands to | Example |
---|---|---|
{OS} | Name of the OS used | Linux, Windows, Darwin, FreeBSD, OpenBSD |
{Version} | Version of Nuitka | e.g. (0, 6, 16) |
{Commercial} | Version of Nuitka Commercial | e.g. (0, 9, 4) |
{Arch} | Architecture used | x86_64, arm64, etc. |
{MAIN_DIRECTORY} | Directory of the compiled file | some_dir/maybe_relative |
{Flavor} | Variant of Python | e.g. Debian Python, Anaconda Python |
当您想要指定相对于主脚本的文件名时,建议使用{MAIN_DIRECTORY},例如用于数据文件选项或用户包配置yaml文件,
# nuitka-project: --include-data-files={MAIN_DIRECTORY}/my_icon.png=my_icon.png
# nuitka-project: --user-package-configuration-file={MAIN_DIRECTORY}/user.nuitka-package.config.yml
对于将-O或-S之类的东西传递给Python,或者传递给编译后的程序,有一个命令行选项名称–Python-flag=,它使Nuitka能够模仿这些选项。
最重要的是得到支持,当然还可以增加更多。
当使用相同的输入文件调用C编译器时,将需要很长时间和大量CPU来反复编译。在使用gcc时(即使在Windows上),请确保已安装并配置了ccache。它将使重复编译更快,即使事情还不完美,也就是说,对程序的更改可能会导致许多C文件发生更改,需要进行新的编译,而不是使用缓存的结果。
在Windows上,有了gcc,Nuitka支持使用ccache.exe,它将提供从官方来源下载并自动下载。这是在Windows上使用它的推荐方式,因为其他版本可以挂起。
如果在系统PATH中找到ccache,Nuitka将拾取它,并且还可以通过将Nuitka_ccache_BINARY设置为二进制文件的完整路径来提供,这适用于可能不标准的CI系统。
对于MSVC编译器和ClangCL设置,使用clcache是自动的,并且包含在Nuitka中。
各种缓存结果、下载、C和Nuitka的缓存编译结果的存储都是在appdirs包确定的依赖于平台的目录中完成的。但是,可以通过将环境变量NUITKA_CACHE_DIR设置为基本目录来覆盖它。这适用于主目录不是持久化的,但其他路径是持久化的环境。
避免运行nuitka二进制文件,执行python-m-nuitka将100%确保您使用的是您认为的内容。使用错误的Python会使它为好的代码提供SyntaxError,为安装的模块提供ImportError。当您在Python3代码上使用Python2运行Nuitka时,就会发生这种情况,反之亦然。通过显式调用相同的Python解释器二进制文件,可以完全避免这个问题。
使用64位Python的pystone.exe在Windows上最快的二进制文件在使用MinGW64时被证明明显更快,得分提高了大约20%。因此,建议在MSVC上使用。使用Clang7的clang-cl.exe比MSVC快,但仍然比MinGW64慢得多,而且更难使用,因此不建议使用。
在pystone.bin的Linux上,clang6生成的二进制文件比gcc-6.3更快,但差距不大。由于gcc通常已经安装,因此建议暂时使用。
C编译时间的差异尚未得到检验。
像标准CPython一样使用Python DLL可能会导致意外的速度减慢,例如在使用Unicode字符串的未编译代码中。这是因为调用DLL而不是驻留在DLL中会导致开销,而且这种情况甚至发生在DLL本身,比一个二进制文件中包含的Python更慢。
因此,如果可行的话,以静态链接为目标,这目前仅适用于非Windows上的Anaconda Python、Debian Python2、自编译Python(不激活-启用共享,不需要)以及使用pyenv创建的安装。
在Anaconda上,您可能需要执行conda-install-libpython-static
传统上,为Windows制作独立可执行文件的过程包括使用外部依赖项助行器,以便将必要的库和编译的可执行文件一起复制到分发文件夹。
有很多方法可以找到缺失的东西。不要手动将东西复制到文件夹中,尤其不要复制DLL,因为这是行不通的。相反,制作错误报告,让Nuitka正确处理这些问题。
在Windows上,Windows Defender工具和Windows索引服务都会扫描新创建的二进制文件,而Nuitka则希望使用它,例如添加更多资源,然后防止由于持有锁而随机执行操作。请确保将编译阶段排除在这些服务之外。
无论是使用MingW还是MSVC编译,独立程序都具有对Visual C运行库的外部依赖关系。Nuitka试图通过从您的系统中复制这些依赖的DLL来运送它们。
从Microsoft Windows 10开始,Microsoft提供了ucrt.dll(通用C运行库),用于处理对api ms-crt-*.dll的调用。
对于早期的Windows平台(以及wine/ReactOS),在执行Nuitka独立编译程序之前,应该考虑安装Visual C运行库。
根据所使用的C编译器,您需要在目标计算机上使用以下redist版本。但是请注意,建议使用基于14.3的版本进行编译。
Visual C version | Redist Year | CPython |
---|---|---|
14.3 | 2022 | 3.11 |
14.2 | 2019 | 3.5, 3.6, 3.7, 3.8, 3.9, 3.10 |
14.1 | 2017 | 3.5, 3.6, 3.7, 3.8 |
14.0 | 2015 | 3.5, 3.6, 3.7, 3.8 |
10.0 | 2010 | 3.3, 3.4 |
9.0 | 2008 | 2.6, 2.7 |
使用MingGW64时,您需要以下redist版本:
MingGW64 version | Redist Year | CPython |
---|---|---|
8.1.0 | 2015 | 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11 |
一旦在目标系统上安装了相应的运行库,您就可以从Nuitka编译的dist文件夹中删除所有api-ms-crt-*.dll文件。
Nuitka不像其他工具那样sys.frozen,因为它通常会无缘无故地触发劣质代码。对于Nuitka,我们有模块属性__compiled__来测试是否编译了特定的模块,函数属性__compile d_来测试是否编辑了特定的函数。
Nuitka将在编译过程中应用环境变量CCFLAGS、LDFLAGS的值,以及它认为必要的值。当然要注意,这只有在你知道自己在做什么的情况下才有用,所以如果这会带来问题,只需提供完美的信息。
Nuitka将自动针对您正在使用的Python的体系结构。如果这是64位,它将创建64位二进制,如果是32位,则它将创建32位二进制。您可以在下载Python时选择位。在python-m nuitka-版本的输出中,有一行是关于体系结构的。It Arch:x86_64用于64位,而just Arch:x86用于32位。
C编译器将被选择来或多或少地自动匹配它。如果您明确指定了它,但它不匹配,您将收到关于不匹配的警告,并被告知您的编译器选择被拒绝。
当您使用–report=compilation-report.xml时,Nuitka将创建一个xml文件,其中包含有关编译和打包过程的详细信息。随着版本的发布,它的完整性越来越高,并暴露了模块使用尝试、编译时间、插件影响、数据文件路径、DLL以及包含或不包含这些内容的原因。
此时,报告包含某些地方的绝对路径以及您的私人信息。我们的目标是在默认情况下将其混合,因为我们还希望能够比较不同设置的编译报告,例如与更新的包,并查看对Nuitka的更改。但是,建议您将该报告用于错误报告。
此外,还提供了另一种形式,其中报告是免费形式,并根据您的Jinja2模板,以及Nuitka中包含的模板。可以访问用于生成XML文件的相同信息。然而,目前还没有对此进行记录,但我们计划添加一个包含数据的表。然而,对于熟悉Jinja2的源代码读者来说,现在已经很容易做到了。
如果你有一个模板,你可以这样使用它——report-template=your_template.rst.j2:your_report.rst,当然,使用重组文本只是一个例子。您可以使用markdown、自己的XML或任何您认为合适的东西。Nuitka将使用编译报告数据扩展模板。
目前,Nuitka中包含以下报告。您只需将该名称用作文件名,Nuitka就会选择该名称。
Report Name | Status | Purpose |
---|---|---|
LicenseReport | experimental | Distributions used in a compilation with license texts |
社区可以而且应该贡献更多的报告类型,并帮助增强现有的报告类型以获得良好的外观。
本章概述了Nuitka目前的业绩预期。这是一项正在进行的工作,并随着我们的进展而更新。目前性能测量的重点是Python2.7,但3.x将在后面介绍。
结果是这种输出的最高值,运行pystone 1000次,取最小值。这个想法是,最快的运行是最有意义的,并消除了使用高峰。
echo "Uncompiled Python2"
for i in {1..100}; do BENCH=1 python2 tests/benchmarks/pystone.py ; done | sort -rn | head -n 1
python2 -m nuitka --lto=yes --pgo tests/benchmarks/pystone.py
echo "Compiled Python2"
for i in {1..100}; do BENCH=1 ./pystone.bin ; done | sort -n | head -rn 1
echo "Uncompiled Python3"
for i in {1..100}; do BENCH=1 python3 tests/benchmarks/pystone3.py ; done | sort -rn | head -n 1
python3 -m nuitka --lto=yes --pgo tests/benchmarks/pystone3.py
echo "Compiled Python3"
for i in {1..100}; do BENCH=1 ./pystone3.bin ; done | sort -rn | head -n 1
Python | Uncompiled | Compiled LTO | Compiled PGO |
---|---|---|---|
Debian Python 2.7 | 137497.87 (1.000) | 460995.20 (3.353) | 503681.91 (3.663) |
Nuitka Python 2.7 | 144074.78 (1.048) | 479271.51 (3.486) | 511247.44 (3.718) |