具有完整语言支持和 CPython 兼容性的 Python 编译器
项目描述
概述
如果您对使用 Nuitka 感兴趣、了解其用例、检查您的期望、许可、要求、信用等,建议您首先阅读本文档。
Nuitka 是Python编译器。它是用 Python 编写的。它是 Python 解释器的无缝替换或扩展,并编译 CPython 2.6、2.7、3.3、3.4、3.5、3.6、3.7、3.8、3.9、3.10 本身与该 Python 版本一起运行时所具有的每个构造。
然后它以极其兼容的方式一起执行未编译的代码和已编译的代码。
您可以自由使用所有 Python 库模块和所有扩展模块。
Nuitka 将 Python 模块转换为 C 级程序,然后使用libpython和它自己的静态 C 文件以与 CPython 相同的方式执行。
所有优化都旨在避免不必要的开销。None 旨在消除兼容性,尽管偶尔会进行轻微改进,其中并非模拟标准 Python 的每个错误,例如给出更完整的错误消息,但有一个完全兼容模式可以禁用它。
用法
要求
C 编译器:您需要一个支持 C11 或 C++03 [ 1 ]的编译器
目前这意味着,您需要使用以下编译器之一:
Windows 上的 MinGW64 C11 编译器,必须基于 gcc 11.2 或更高版本。如果没有找到可用的 C 编译器,它将自动下载,这是推荐的安装方式,因为 Nuitka 也会为您升级它。
Windows [ 2 ]上的 Visual Studio 2022 或更高版本,旧版本也可以使用,但仅支持商业用户。配置为使用英语语言包以获得最佳效果(Nuitka 过滤掉垃圾输出,但仅适用于英语语言)。如果安装,它将默认使用。
在所有其他平台上,至少版本 5.1的gcc编译器,以及低于该版本的至少版本 4.4的g++编译器作为替代。
macOS X 和大多数 FreeBSD 架构上的clang编译器。
在 Windows上,如果 Visual Studio 安装程序提供,则可以使用Windows 上的clang-cl编译器。
Python:版本 2.6、2.7 或 3.3、3.4、3.5、3.6、3.7、3.8、3.9、3.10
操作系统:Linux、FreeBSD、NetBSD、macOS X 和 Windows(32/64 位)。
其他人也可以工作。预计可移植性通常很好,但可能必须调整例如 Scons 的使用。确保匹配 Windows Python 和 C 编译器架构,否则您将收到神秘的错误消息。
架构:x86、x86_64 (amd64) 和 arm,可能还有更多
预计其他架构也可以开箱即用,因为 Nuitka 通常不使用任何硬件细节。这些只是经过测试并已知良好的产品。欢迎反馈。一般来说,Debian 支持的架构也可以被认为是好的并且经过测试。
命令行
执行 Nuitka 的推荐方式是<the_right_python> -m nuitka以绝对确定您使用的是哪个 Python 解释器,因此更容易与 Nuitka 匹配。
执行 Nuitka bare 的下一个最佳方法是从源代码签出或存档,无需更改环境变量,最值得注意的是,对于 Nuitka,您根本不必使用PYTHONPATH。您只需直接执行nuitka和nuitka-run脚本,无需对环境进行任何更改。为方便起见,您可能希望将 bin目录添加到PATH中,但该步骤是可选的。
此外,如果您想使用正确的解释器执行,在这种情况下,请务必执行<the_right_python> bin/nuitka并做好。
Nuitka 有一个--help选项来输出它可以做什么:
nuitka --help
nuitka -run命令与nuitka相同,但具有不同的默认值。它尝试编译并直接执行 Python 脚本:
nuitka-run --help
这个不同的选项是--run,并在第一个非选项之后将参数传递给创建的二进制文件,因此它有点类似于普通python将执行的操作。
安装
对于大多数系统,Nuitka的下载页面上都会有包。但是您也可以如上所述从源代码安装它,但也可以像任何其他 Python 程序一样通过普通的python setup.py 安装例程安装它。
执照
Nuitka 根据 Apache 许可证 2.0 版获得许可;除非遵守许可,否则您不得使用它。
您可以在http://www.apache.org/licenses/LICENSE-2.0上获取许可证的副本
除非适用法律要求或书面同意,否则根据许可分发的软件将按“原样”分发,没有任何明示或暗示的保证或条件。有关许可下的特定语言管理权限和限制,请参阅许可。
教程 在 Windows 上设置和构建
如果您没有安装任何东西,这是基本步骤,当然如果您有任何部件,请跳过它。
设置
安装 Python
从https://www.python.org/downloads/windows下载并安装 Python
选择Windows x86-64 基于 Web 的安装程序(64 位 Python,推荐)或x86 可执行文件(32 位 Python)安装程序之一。
使用命令python --version验证它是否正常工作。
安装 Nuitka
python -m pip install nuitka
使用命令python -m nuitka --version进行验证
写一些代码并测试
为 Python 代码创建一个文件夹
mkdir HelloWorld
制作一个名为hello.py的 python 文件
def talk(message):
return "Talk " + message
def main():
print(talk("Hello World"))
if __name__ == "__main__":
main()
测试你的程序
照常做。在运行不正常的代码上运行 Nuitka 并不容易调试。
python hello.py
使用它构建它
python -m nuitka hello.py
运行
执行在hello.py附近创建的hello.exe。
分发
要分发,请使用--standalone选项构建,该选项不会输出单个可执行文件,而是输出整个文件夹。将生成的 hello.dist文件夹复制到另一台机器并运行它。
您也可以尝试创建单个文件的--onefile,但在转向它之前,请确保仅独立的文件正在工作,因为它只会使调试更加困难,例如在丢失数据文件的情况下。
用例
用例 1 - 嵌入所有模块的程序编译
如果您想递归编译整个程序,而不仅仅是作为主程序的单个文件,请这样做:
python -m nuitka --follow-imports program.py
如果您有一个包含动态加载文件的源目录,即无法通过PYTHONPATH的正常导入语句后递归找到的源目录(这将是推荐的方式),您始终可以要求给定目录也应包含在可执行:
python -m nuitka --follow-imports --include-plugin-directory=plugin_dir program.py
用例 2 - 扩展模块编译
如果你想编译单个扩展模块,你所要做的就是:
python -m nuitka --module some_module.py
然后可以使用 生成的文件some_module.so代替some_module.py。
用例 3 - 包编译
如果你需要编译整个包并嵌入所有模块,这也是可行的,像这样使用Nuitka:
python -m nuitka --module some_package --include-package=some_package
用例 4 - 程序分发
对于分发到其他系统,存在独立模式,它会生成一个文件夹,您可以为其指定--standalone。
python -m nuitka --standalone program.py
在此模式下,默认遵循所有导入。您可以通过明确地说--nofollow-import-to来选择性地排除模块,但是 在程序运行时尝试导入它时会引发ImportError 。
对于要包含的数据文件,请使用选项 --include-data-files=<source>=<target>其中源是文件系统路径,但目标必须是相对的。对于独立模式,您也可以手动复制它们,但这可以进行额外的检查,而对于单文件模式,则无法手动复制。
要复制目录中的部分或全部文件,请使用选项 --include-data-files=/etc/*.txt=etc/在其中指定文件的 shell 模式,以及放置它们的子目录,指示通过斜杠。
要复制包含所有文件的整个文件夹,您可以使用 --include-data-dir=/path/to/images=images这将复制所有文件,包括潜在的子目录结构。您不能在此处过滤,即如果您只想要部分副本,请事先删除文件。
对于包数据,有一种更好的方法,使用 --include-package-data自动检测包的数据文件并将它们复制过来。它甚至接受 shell 样式的模式。
使用数据文件,您主要靠自己。Nuitka 会跟踪流行包所需的包,但它可能不完整。如果您遇到这些问题,请提出问题。
当它工作时,如果你愿意,你可以使用 onefile 模式。
python -m nuitka --onefile program.py
这将创建一个二进制文件,在 Linux 上它甚至不会自行解包,而是将其内容作为文件系统循环安装并使用它。
# Create a binary that unpacks into a temporary folder
python -m nuitka --onefile program.py
同样,在 Windows 上,对于临时文件目录,默认情况下使用用户一个,但是可以使用--windows-onefile-tempdir-spec=%TEMP%\\onefile_%PID%_中给出的路径规范覆盖它%TIME% 是默认值,它断言创建的临时目录不会发生冲突。
目前这些扩展令牌可用:
令牌 |
这扩展到什么 |
例子 |
---|---|---|
%温度% |
用户临时文件目录 |
C:用户...AppDataLocalsTemp |
%PID% |
进程 ID |
2772 |
%时间% |
自纪元以来的时间(以秒为单位)。 |
1299852985 |
%程序% |
可执行文件的完整程序运行时文件名。 |
C:SomeWhereYourOnefile.exe |
%CACHE_DIR% |
用户的缓存目录。 |
C:UsersSomeBodyAppDataLocal |
%公司% |
以--windows-company-name 形式给出的值 |
您的公司名称 |
%产品% |
以--windows-product-name 形式给出的值 |
您的产品名称 |
%版本% |
--windows-file-version和--windows-product-version 的组合 |
3.0.0.0-1.0.0.0 |
%家% |
用户的主目录。 |
/家/某人 |
用例 5 - Setuptools Wheels
如果您有一个setup.py、setup.cfg或pyproject.toml驱动为您的软件创建轮子,那么使用 Nuitka 非常容易。
让我们从最常见的setuptools方法开始,您可以 - 当然安装了 Nuitka,只需执行目标 bdist_nuitka而不是bdist_wheel。它接受所有选项,并允许您指定更多特定于 Nuitka 的选项。
# 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
)
或者你可以把它放在你的setup.cfg
[metadata]
build_with_nuitka = True
最后但并非最不重要的一点是,Nuitka 还支持新的构建元,所以当你已经有一个pyproject.toml时,简单地替换或添加这个值:
[build-system]
requires = [<s>"setuptools>=42"</s>, <s>"wheel"</s>, <s>"nuitka"</s>, <s>"toml"</s>]
build-backend = <s>"nuitka.distutils.Build"</s>
[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 = [<s>"*.tests"</s>, <s>"*.distutils"</s>]
调整
图标
为了美观,您可以指定图标。在 Windows 上,您可以提供图标文件、模板可执行文件或 PNG 文件。所有这些都将起作用,甚至可以结合起来:
# These create binaries with icons:
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
启动画面
当程序启动缓慢时,启动画面很有用。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.
典型问题
内存问题和编译器错误
有时 C 编译器会崩溃,说他们无法分配内存或某些输入被截断,或类似的错误消息,显然来自它。您可以在这里探索几个选项:
让 Nuitka 使用更少的内存
有一个专门的选项--low-memory会影响 Nuitka 的决策,从而避免在编译期间以增加编译时间为代价的高内存使用。
避免 32 位 C 编译器/汇编器内存限制
不要使用 32 位编译器,而是使用 64 位编译器。如果你在 Windows 上使用 32 位 Python,你绝对应该使用 MSVC 作为 C 编译器,而不是 MinGW64。MSVC 是一个交叉编译器,在该平台上可以使用比 gcc 更多的内存。如果您不在 Windows 上,那当然不是一种选择。也可以使用 64 位 Python。
使用最小的 virtualenv
当您从实时安装编译时,很可能会安装许多可选的软件依赖项。一些软件会在这些上导入,Nuitka 也会编译它们。这些不仅可能只是麻烦制造者,而且还需要更多内存,因此请摆脱它。当然,您必须在尝试编译之前检查您的程序是否具有所有需要的依赖项,否则编译后的程序将同样无法运行。
是否使用 LTO 编译
使用--lto=yes或--lto=no可以将 C 编译切换为只生成字节码,而不是直接生成汇编代码和机器码,而是在最后进行整个程序优化。这将极大地改变内存使用情况,如果您的错误来自汇编程序,使用 LTO 绝对可以避免这种情况。
将 C 编译器切换到 clang
人们报告说,由于 gcc 的错误或内存使用而无法使用 gcc 编译的程序在 Linux 上可以正常使用 clang。在 Windows 上,这仍然是一个选项,但需要首先为自动下载的 gcc 实现它,这将包含它。由于众所周知 MSVC 无论如何都更有效地存储内存,因此您应该去那里,如果您想使用 Clang,则支持 MSVC 中包含的那个。
将更大的交换文件添加到您的嵌入式 Linux
在没有足够 RAM 的系统上,您需要使用交换空间。用完它可能是一个原因,添加更多的交换空间,或者根本没有,可能会解决这个问题,但要注意当编译器来回交换时它会使事情变得非常慢,所以首先考虑下一个技巧最重要的是。
限制编译作业的数量
使用 Nuitka 的--jobs选项,它不会一次启动许多 C 编译器实例,每个实例都竞争稀缺的 RAM 资源。通过选择一个值,只有一个 C 编译器实例将运行,并且在一个 8 核系统上,这将内存量减少了 8 倍,所以这是一个自然的选择。
动态系统路径
如果您的脚本将sys.path修改为例如插入包含与其相关的源代码的目录,Nuitka 将无法看到这些目录。但是,如果您将PYTHONPATH设置为结果值,它将能够编译它并从这些路径中找到使用的模块。
手动 Python 文件加载
私有代码的一个非常常见的模式是它扫描某种插件目录,并使用os.listdir,检查文件名,然后打开一个文件并对其执行exec。这种方法适用于 Python 代码,但对于编译后的代码,您应该使用这种更简洁的方法,它适用于纯 Python 代码并且不易受到攻击。
# Using a package name, to locate the plugins, but this can actually
# be also a directory.
scan_path = scan_package.__path__
for item in pkgutil.iter_modules(scan_path):
# You may want to do it recursively, but we don't do this here in
# this example.
if item.ispkg:
continue
# The loader object knows how to do it.
module_loader = item.module_finder.find_module(item.name)
# Ignore bytecode only left overs. Deleted files can cause
# these things, so we just ignore it. Not every load has a
# filename, so we need to catch that error.
try:
if module_loader.get_filename().endswith(".pyc"):
continue
except AttributeError:
# Not a bytecode loader, but e.g. extension module, which is OK in case
# it was compiled with Nuitka.
pass
plugin_module = module_loader.load_module(item.name)
# At least for Python2, this is not set properly, but we use it for package
# data loading, so this manual patching up allows these to use proper methods
# for loading their stuff as well.
plugin_module.__package__ = scan_package.__name__
独立中缺少数据文件
如果您的程序无法归档数据,它可能会导致各种不同的行为,例如,一个包可能会抱怨它不是正确的版本,因为VERSION文件检查默认为未知。缺少图标文件或帮助文本可能会引发奇怪的错误。
通常,不存在的文件的错误路径甚至是错误的,并且会显示编程错误,例如未绑定的局部变量。请仔细查看这些异常,记住这可能是原因。如果您的程序没有独立运行,则可能是数据文件。
缺少独立的 DLL
Nuitka 有处理复制 DLL 的插件。对于 NumPy、SciPy、Tkinter 等。
这些需要特殊处理才能在其他系统上运行。手动复制它们是不够的,并且会出现奇怪的错误。有时更新版本的软件包,尤其是。NumPy 可能不受支持。在这种情况下,您将不得不提出一个问题,并使用较旧的问题。
独立中的依赖性蔓延
有些包是一次导入,但对于 Nuitka 来说意味着要包含一千多个包(字面意思)。Pandas 的主要例子,它确实想要插入和使用几乎所有你能想象到的东西。用于突出显示所有可以想象的所有内容的多个语法框架需要时间。
Nuitka 将来必须学习有效的缓存来处理这个问题。现在,您将不得不为这些处理大量的编译时间。
应该使用对抗依赖蠕变的主要武器,即anti-bloat插件,它提供了有趣的功能,可以使用并阻止不需要的导入,并在它们发生的位置给出错误。像这样使用它--noinclude-pytest-mode=nofollow --noinclude-setuptools-mode=nofollow和 --noinclude-custom-mode=setuptools:error来让编译器为特定的包出错。确保检查其帮助输出。它可以用于您选择的每个模块,例如,还强制例如 PyQt5被认为已卸载以用于独立模式。
它还由您可以贡献的配置文件anti-bloat.yml驱动,从包中删除典型的膨胀。随意增强它并用它对 Nuitka 进行 PR。
Onefile:查找文件
onefile more 的主模块的sys.argv[0]和__file__之间存在差异,这是由于使用引导程序到临时位置引起的。第一个将是原始可执行文件路径,而第二个将是引导可执行文件解压缩到的临时或永久路径。数据文件将在后面的位置,您的原始环境文件将在前面的位置。
给定 2 个文件,一个您希望在可执行文件附近,另一个您希望在 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"))
独立:查找文件
通常可以使用的标准代码也可以使用,您应该参考 os.path.dirname(__file__)或使用pkgutil、 pkg_resources、importlib.resources等所有软件包来定位独立二进制文件附近的数据文件。
没有控制台的 Windows 程序没有错误
出于调试目的,删除--windows-disable-console或使用选项--windows-force-stdout-spec和 --windows-force-stderr-spec以及上述--windows-onefile-tempdir-spec记录的路径 .
深拷贝未编译的函数
有时人们会使用这种代码,对于 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
提示
代码中的 Nuitka 选项
支持条件选项和使用预定义变量的选项,这是一个示例:
# 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").__version__如果需要启用或禁用某些 Nuitka 设置。Nuitka 做的唯一一件不是 Python 表达式的事情,就是将{variable}扩展 为一组预定义的变量:
包含支持变量的表:
多变的 |
这扩展到什么 |
例子 |
---|---|---|
{操作系统} |
使用的操作系统名称 |
Linux、Windows、达尔文、FreeBSD、OpenBSD |
{版本} |
Nuitka 版本 |
例如 (0, 6, 16) |
{商业的} |
Nuitka 商业版 |
例如 (0, 9, 4) |
{拱} |
使用的架构 |
x86_64、arm64 等 |
{MAIN_DIRECTORY} |
编译文件目录 |
some_dir/maybe_relative |
{味道} |
Python 的变体 |
例如 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
Python 命令行标志
为了将-O或-S之类的东西传递给 Python,到你的编译程序,有一个命令行选项名称--python-flag=使 Nuitka 模拟这些选项。
支持最重要的,当然可以添加更多。
缓存编译结果
当使用相同的输入文件调用 C 编译器时,将需要很长时间和大量 CPU 来一遍又一遍地编译。确保在使用 gcc 时安装和配置了 ccache(即使在 Windows 上也是如此)。即使事情还不完美,它也会使重复编译更快,即对程序的更改会导致许多 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 解释器二进制文件,您可以完全避免该问题。
最快的 C 编译器
使用 64 位 Python 的 Windows 上最快的pystone.exe二进制文件在使用 MinGW64 时速度明显更快,大约高出 20%。因此建议在 MSVC 上使用。使用Clang7 的clang-cl.exe比 MSVC 快,但还是比 MinGW64 慢很多,而且会比较难用,所以不推荐。
在 Linux for pystone.bin上,由clang6生成的二进制文件比gcc-6.3快,但差距不大。由于 gcc 经常已经安装,因此建议现在使用。
尚未检查 C 编译时间的差异。
意外放缓
像标准 CPython 一样,使用 Python DLL 会导致意外减速,例如在使用 Unicode 字符串的未编译代码中。这是因为调用 DLL 而不是驻留在 DLL 中会导致开销,甚至 DLL 本身也会发生这种情况,比一个二进制文件中包含的 Python 更慢。
因此,如果可行,请针对静态链接,这目前仅适用于非 Windows 上的 Anaconda Python、Debian Python2、自编译 Python(不要激活--enable-shared,不需要),以及使用pyenv创建的安装。
独立的可执行文件和依赖项
为 Windows 制作独立可执行文件的过程传统上涉及使用外部依赖遍历器,以便将必要的库与已编译的可执行文件一起复制到分发文件夹。
有很多方法可以找到缺少的东西。不要手动将东西复制到文件夹中,尤其是。不是DLL,因为那是行不通的。而是制作错误报告以让 Nuitka 正确处理这些问题。
Windows 资源错误
在 Windows 上,Windows Defender 工具和 Windows 索引服务都扫描新创建的二进制文件,而 Nuitka 想要使用它,例如添加更多资源,然后由于持有锁而防止随机操作。确保从这些服务中排除您的编译阶段。
Windows 独立程序重新分发
无论是使用 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 版本:
视觉 C 版本 |
重新分配年份 |
CPython |
---|---|---|
14.2 |
2019 |
3.5、3.6、3.7、3.8、3.9、3.10 |
14.1 |
2017 |