You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cython编译项目为.pyd文件后multiprocessing模块无法正常工作的解决方案求助

Cython编译项目为.pyd文件后multiprocessing模块无法正常工作的解决方案求助

最近几个小时我一直在啃一个棘手的问题:把项目用Cython编译成纯.pyd文件后,multiprocessing模块彻底没法正常工作了。我选择这种方式的原因很明确——远程机器上绝对不能出现源码;之前试过PyInstaller,但它实在太不稳定了,编译时总是缺失多个依赖包的.dll文件,就算好不容易调稳定了,只要新增或者更新一个包的版本,整个程序就可能崩掉,所以实在不想再用它。

编译生成.pyd文件后,我写了一个main.py文件,从编译好的main.pyd里导入启动函数,以此来启动整个工作流程。我的项目规模不算小,大概有40-50个文件。

下面是我用来生成.pyd文件的setup.py代码:

from distutils.core import setup
from Cython.Build import cythonize
import os

# Recursively collect all Python files in the folder
def collect_files(base_dir):
    extensions = []
    for root, dirs, files in os.walk(base_dir):
        if "brainstorming" in dirs:
            dirs.remove("brainstorming")
        if "venv" in dirs:
            dirs.remove("venv")
        for file in files:
            if file.endswith(".py"):  # Include all Python files
                full_path = os.path.join(root, file)
                module_path = os.path.splitext(full_path.replace(base_dir + os.sep, "").replace(os.sep, "."))[0]
                extensions.append(full_path)
    return list(set(extensions))  # Ensure unique paths

base_dir = "."
extensions = collect_files(base_dir)

setup(
    name="myproj",
    ext_modules=cythonize(
        extensions,
        compiler_directives={
            "language_level": "3"}
    ),
    zip_safe=True,
)

问题出在这段启动子进程的代码上:

Process(target=output_process, daemon=True, args=(<arg 1>, <arg2> ...)).start()

看起来Python的multiprocessing模块在尝试pickle这个cyfunction的时候,会动态导入该函数所在的模块,但每次都以失败告终。

output_process函数位于和调用它的文件同级的lib文件夹下,具体是lib/outputprocess.py文件,项目目录结构如下:

Project/
|-- module/
|   |-- lib/
|   |   |-- __init__.py
|   |   |-- outputprocess.py 
|   |-- __init__.py
|   |-- module_that_calls_multiprocessing.py

不管我怎么调整,只要运行到启动子进程这一步,就会抛出这个异常:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\spaceflux\anaconda3\Lib\multiprocessing\spawn.py", line 122, in spawn_main
    exitcode = _main(fd, parent_sentinel)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\spaceflux\anaconda3\Lib\multiprocessing\spawn.py", line 132, in _main
    self = reduction.pickle.load(from_parent)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ModuleNotFoundError: No module named 'outputprocess'

用普通.py文件运行项目的时候一切正常,模块肯定是存在的。

我还试过把output_process函数移到调用它的同一个文件里测试,结果又出现了另一个错误:

File "C:\Users\spaceflux\anaconda3\Lib\multiprocessing\process.py", line 121, in start
    self._popen = self._Popen(self)
                  ^^^^^^^^^^^^^^^^^
  File "C:\Users\spaceflux\anaconda3\Lib\multiprocessing\context.py", line 224, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\spaceflux\anaconda3\Lib\multiprocessing\context.py", line 336, in _Popen
    return Popen(process_obj)
           ^^^^^^^^^^^^^^^^^^
  File "C:\Users\spaceflux\anaconda3\Lib\multiprocessing\popen_spawn_win32.py", line 94, in __init__
    reduction.dump(process_obj, to_child)
  File "C:\Users\spaceflux\anaconda3\Lib\multiprocessing\reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <cyfunction output_process at 0x0000023151445970>: import of module '<my module>' failed

有没有大佬能给点解决思路?我真的挺喜欢.pyd这种方式的,编译速度快,在生产环境里调试和打热补丁也方便,但如果有其他可行的方案我也愿意尝试!

备注:内容来源于stack exchange,提问作者Martin Todorov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 13:58:06