Python,Windows和Multiprocessing

我有一个最初build立在Linux上的Python程序,现在我正试图移植到Windows。 我正在虚拟环境中运行该程序,其中包含所有的依赖关系(我的程序安装为pip install –find-links wheels my_module)。 该计划与推出

(venv) C:\>venv\Scripts\python.exe -m base_module.Launcher arg1 arg2 

base_module根据提供的参数加载我的模块,他的相关代码是:

 from multiprocessing.managers import SyncManager import OtherCustomClass class BaseModule(object): def __init__(self, arg1, arg2): self.manager = SyncManager() self.manager.start(ignore_interrupt) def main(argv=None): ret = -1 try: basmod = BaseModule(argv[0], argv[1]) ret = basmod.run() except Exception, err: print("error: " + str(err)) print(traceback.format_exc()) return ret if __name__ == "__main__": exitCode = main(sys.argv[1:]) sys.exit(exitCode) 

这在Linux中工作正常,但在Windows上,我得到以下exception:

 Traceback (most recent call last): File "<string>", line 1, in <module> File "C:\Python27\Lib\multiprocessing\forking.py", line 380, in main prepare(preparation_data) File "C:\Python27\Lib\multiprocessing\forking.py", line 505, in prepare '__parents_main__', file, path_name, etc File "build/bdist.linux-x86_64/egg/base_module/BaseModule.py", line 2, in <module> ImportError: No module named OtherCustomClass exception in main: Traceback (most recent call last): File "build/bdist.linux-x86_64/egg/base_module/BaseModule.py", line 12, in main File "build/bdist.linux-x86_64/egg/base_module/BaseModule.py", line 7, in __init__ File "C:\Python27\Lib\multiprocessing\managers.py", line 528, in start self._address = reader.recv() EOFError 

后者的EOFError是由SyncManager中分叉的意外提前终止引起的,其中真正的错误无法导入OtherCustomClass。 我已经证实,OtherCustomClass存在于venv / lib / site-packages中的base_module文件夹中,并且当我首先启动模块时,这个错误不会发生,因为Python永远不会到达main()或init中的指令,编译。

我已经做了一些研究,而且我知道这个问题已经打击了其他人(通常使用第三方库,在没有发布解决scheme的情况下解决了问题)。 它似乎追溯到Windows缺乏fork(),以及python在Windows上处理多处理 – 另见http://docs.python.org/library/multiprocessing.html#windows 。 但是我不知道如何解决这个问题。

这是最新的Python 2.7分支(2.7.8),运行在Windows 7 x64上。

您可以通过对OtherCustomClass使用绝对导入来解决此OtherCustomClass

 from base_module import OtherCustomClass 

我不是很确定为什么,但似乎multiprocessing产生一个新的进程,并导入您的__main__ ,它不能处理您使用与OtherCustomClass隐式相对导入。 如果你明确从base_module导入它,它可以正常工作。 我的猜测是生成的子进程不被识别为base_module包的一部分,所以隐式导入失败,但这只是一个猜测。

请注意, 您不应该使用隐式相对导入 (它们完全从Python 3中删除),因此切换到绝对导入不是一件坏事。

另外值得注意的是,在Python 3.4上做一个明确的相对导入:

 from . import OtherCustomClass 

但它在Python 2.7上失败:

 Traceback (most recent call last): File "<string>", line 1, in <module> File "C:\python27\lib\multiprocessing\forking.py", line 380, in main prepare(preparation_data) File "C:\python27\lib\multiprocessing\forking.py", line 495, in prepare '__parents_main__', file, path_name, etc File "C:\Users\oreild1\Desktop\base_module\Launcher.py", line 5, in <module> from . import OtherCustomClass ValueError: Attempted relative import in non-package error: Traceback (most recent call last): File "C:\Users\oreild1\Desktop\base_module\Launcher.py", line 18, in main basmod = Basemodulee(argv[0], argv[1]) File "C:\Users\oreild1\Desktop\base_module\Launcher.py", line 10, in __init__ self.manager.start() File "C:\python27\lib\multiprocessing\managers.py", line 528, in start self._address = reader.recv() EOFError