Cythonize 以 'fatal error C1002: compiler is out of heap space in pass 2' 结尾

Cythonize ends with 'fatal error C1002: compiler is out of heap space in pass 2'

我尝试用 cythonize 一个 .py 脚本。它是一个带有大量 QToolButtons 和一个有效的 EventFilter 的 PyQt5 gui。 c模块构建成功,但是编译失败,报如下错误:

d:\stuff\mapform2a.c(11338) : fatal error C1002: compiler is out of heap space in pass 2 LINK : fatal error LNK1257: code generation failed error: command 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\link.exe' failed with exit status 1257

编译器来自Visual Studio 2019.Python 3.5.5(是的,旧的,我知道,但我有理由......)。

尝试“cythonize -i script.py”时有什么方法可以增加堆 space 吗?

Cython 文档对此确实不清楚(至少对于非 C 专家...)

编辑 完整日志如下:

C:\temp\MapForm>python setup.py build_ext --inplace Compiling MapForm2A.py because it changed. [1/1] Cythonizing MapForm2A.py C:\Anaconda3\lib\site-packages\Cython\Compiler\Main.py:369: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: C:\temp\MapForm\MapForm2A.py tree = Parsing.p_module(s, pxd, full_module_name) running build_ext building 'MapForm2A' extension creating build creating build\temp.win-amd64-3.5 creating build\temp.win-amd64-3.5\Release C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -IC:\Anaconda3\include -IC:\Anaconda3\include "-IC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE" "-IC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\ATLMFC\INCLUDE" "-IC:\Program Files (x86)\Windows Kits\include.0.18362.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\include.0.18362.0\shared" "-IC:\Program Files (x86)\Windows Kits\include.0.18362.0\um" "-IC:\Program Files (x86)\Windows Kits\include.0.18362.0\winrt" /TcMapForm2A.c /Fobuild\temp.win-amd64-3.5\Release\MapForm2A.obj MapForm2A.c creating C:\temp\MapForm\build\lib.win-amd64-3.5 C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\link.exe /nologo /INCREMENTAL:NO /LTCG /DLL /MANIFEST:EMBED,ID=2 /MANIFESTUAC:NO /LIBPATH:C:\Anaconda3\libs /LIBPATH:C:\Anaconda3\PCbuild\amd64 "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\LIB\amd64" "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\ATLMFC\LIB\amd64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\lib.0.18362.0\ucrt\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\lib.0.18362.0\um\x64" /EXPORT:PyInit_MapForm2A build\temp.win-amd64-3.5\Release\MapForm2A.obj /OUT:build\lib.win-amd64-3.5\MapForm2A.cp35-win_amd64.pyd /IMPLIB:build\temp.win-amd64-3.5\Release\MapForm2A.cp35-win_amd64.lib MapForm2A.obj : warning LNK4197: export 'PyInit_MapForm2A' specified multiple times; using first specification Creating library build\temp.win-amd64-3.5\Release\MapForm2A.cp35-win_amd64.lib and object build\temp.win-amd64-3.5\Release\MapForm2A.cp35-win_amd64.exp Generating code c:\temp\mapform\mapform2a.c(7545) : fatal error C1002: compiler is out of heap space in pass 2 LINK : fatal error LNK1257: code generation failed error: command 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\link.exe' failed with exit status 1257

我只能补充一点,在引发 C1002 异常之前,进程在“生成代码”消息上卡住了大约 90 秒。

设置文件比较标准:

from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("MapForm2A.py")
)

该模块是纯 PyQt5(pyuic5 输出),没有其他依赖项,如果不使用 Cython 直接解释,则可以正常工作。

编辑:解决方案(也许有人需要它)。 感谢@DavidW(在下面的评论中讨论)。

Setup.py 必须按以下方式修改:

from distutils import _msvccompiler
_msvccompiler.PLAT_TO_VCVARS['win-amd64'] = 'amd64'

from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("MapForm2A.py"),
)

前两行强制使用 64 位工具链。

为了对评论中解决的问题给出更多解释:基本问题看起来是你正在编译一些大而复杂的东西,而 MSVC 在链接时 运行 内存不足步骤。

Microsoft 有 a page about this error 建议了多种选择,其中主要的一种是使用 64 位编译器。 (请注意,这与您编译的是 32 位还是 64 位模块无关——它只是编译器可执行文件的选择)

编译 Python 扩展模块(尤其是 setup.py)时,编译器设置通常由 distutils 选择。不幸的是,distutils 似乎选择强制使用 32 位编译器(参见 https://github.com/python/cpython/blob/e488e300f5c01289c10906c2e53a8e43d6de32d8/Lib/distutils/_msvccompiler.py#L160)。

我的建议是深入研究 setup.py 顶部的 distutils 内部结构(在进行任何实际设置之前)以覆盖此设置

from distutils import _msvccompiler
_msvccompiler.PLAT_TO_VCVARS['win-amd64'] = 'amd64'

基本上你真正做的就是将选项 amd64 传递给微软提供的 vcvarsall.bat 脚本来设置他们的编译器,从而得到一个 64 位编译器来构建一个 64-位扩展。