【问题标题】:Python, Windows, and MultiprocessingPython、Windows 和多处理
【发布时间】:2014-11-20 09:26:08
【问题描述】:

我有一个最初为 Linux 构建的 Python 程序,我现在正尝试将其移植到 Windows。我在包含所有依赖项的虚拟环境中运行该程序(我的程序安装为带有 pip install --find-links Wheel 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 上出现以下异常:

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 中的说明strong> 如果脚本无法编译。

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

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

【问题讨论】:

  • 您的代码示例中是否存在缩进错误? main 根本不会像您将其用作 BaseModule 的实例方法那样工作。
  • 哎呀,是的。我删减了大量代码来捕捉这里相关的内容,这是一个疏忽
  • @user2093082 这是否通过最小示例为您重现?如果你在 virtualenv 之外运行它会重现吗?
  • 我将软件包安装到主要的 python 安装并使用系统 python 在虚拟环境之外复制。我将尝试使用示例代码进行复制
  • @user2093082 实际上,我能够在 Windows 上重现它。我已经找到了解决方案,但我还不确定根本原因。

标签: python windows multiprocessing virtualenv python-import


【解决方案1】:

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

from base_module import OtherCustomClass

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

请注意you shouldn't be using implicit relative imports anyway(它们已完全从 Python 3 中删除),因此切换到绝对导入并不是一件坏事。

另外值得注意的是,explicit 相对导入适用于 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 = BaseModule(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

【讨论】:

  • 这是完美的——我最初是按文件名导入的(在 Linux 中工作),但我们发现在 Windows 中不能工作,可能是由于分叉。导入模块并从中选择类是可行的。
猜你喜欢
  • 1970-01-01
  • 2020-07-18
  • 1970-01-01
  • 1970-01-01
  • 2020-06-27
  • 1970-01-01
  • 2015-10-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多