【问题标题】:Cythonize ends with 'fatal error C1002: compiler is out of heap space in pass 2'Cythonize 以“致命错误 C1002:编译器在传递 2 中的堆空间不足”结束
【发布时间】:2021-03-19 16:12:53
【问题描述】:

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

d:\stuff\mapform2a.c(11338) : 致命错误 C1002: 编译器在 pass 2 中的堆空间不足 链接:致命错误 LNK1257:代码生成失败 错误:命令 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\link.exe' 失败,退出状态为 1257

编译器来自 Visual Studio 2019。Python 3.5.5(是的,旧的,我知道,但我有原因……)。

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

Cython 文档对此并不清楚(至少对于非 C 专家来说......)

编辑 完整日志如下:

C:\temp\MapForm>python setup.py build_ext --inplace 编译 MapForm2A.py 因为它改变了。 [1/1] Cythonizing MapForm2A.py C:\Anaconda3\lib\site-packages\Cython\Compiler\Main.py:369: FutureWarning:未设置 Cython 指令“language_level”,使用 2 表示 现在(Py2)。这将在以后的版本中更改!文件: C:\temp\MapForm\MapForm2A.py 树 = Parsing.p_module(s, pxd, full_module_name) 运行 build_ext 构建“MapForm2A”扩展 创建 build 创建 build\temp.win-amd64-3.5 创建 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\10\include\10.0.18362.0\ucrt" "-IC:\Program Files (x86)\Windows 套件\10\include\10.0.18362.0\shared" "-IC:\Program Files (x86)\Windows 套件\10\include\10.0.18362.0\um" "-IC:\Program Files (x86)\Windows 套件\10\include\10.0.18362.0\winrt" /TcMapForm2A.c /Fobuild\temp.win-amd64-3.5\Release\MapForm2A.obj MapForm2A.c 创建 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 /增量:否 /LTCG /DLL /清单:嵌入,ID = 2 /清单:否 /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 工具包\10\lib\10.0.18362.0\ucrt\x64" "/LIBPATH:C:\Program 文件 (x86)\Windows 工具包\10\lib\10.0.18362.0\um\x64" /EXPORT:PyInit_MapForm2A 构建\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:警告 LNK4197:指定导出“PyInit_MapForm2A” 多次;使用第一个规范创建库 build\temp.win-amd64-3.5\Release\MapForm2A.cp35-win_amd64.lib 和 对象构建\temp.win-amd64-3.5\Release\MapForm2A.cp35-win_amd64.exp 生成代码 c:\temp\mapform\mapform2a.c(7545):致命错误 C1002: 编译器在 pass 2 LINK 中的堆空间不足:致命错误 LNK1257: 代码生成失败错误:命令'C:\ Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\link.exe' 失败,退出状态 1257

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

设置文件比较标准:

from setuptools import setup
from Cython.Build import cythonize

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

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

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

必须通过以下方式修改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 位工具链。

【问题讨论】:

  • 使用 64 位工具链:stackoverflow.com/q/3508173/5769463
  • @ead 我认为你是对的,但看起来 distutils 很难强制使用 32 位工具链 github.com/python/cpython/blob/…
  • @BartM 在没有其他想法的情况下,您可能应该将脚本细分为更小的模块。另请注意,这听起来不像是真正受益于 Cython 的事情 - 也许考虑一下是否值得付出努力
  • 查看整个日志也会有所帮助。看起来链接器而不是编译器失败了。禁用链接时间代码生成就足够了。
  • 可能只是= 'amd64' 而不是= 'amd64_amd64'?如果这不起作用,那么我没有建议

标签: cython cythonize


【解决方案1】:

为了对 cme​​ts 中解决的问题提供更多解释:基本问题看起来是您正在编译一些大而复杂的东西,并且 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 位扩展。

【讨论】:

    猜你喜欢
    • 2014-07-17
    • 1970-01-01
    • 1970-01-01
    • 2011-06-04
    • 2018-12-21
    • 2020-06-13
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多