【问题标题】:Multiprocessing code works upon import, breaks upon being called多处理代码在导入时起作用,在被调用时中断
【发布时间】:2015-04-28 03:04:14
【问题描述】:

在一个名为 test.py 的文件中,我有

print 'i am cow'
import multi4
print 'i am cowboy'

multi4.py 我有

import multiprocessing as mp
manager = mp.Manager()
print manager

我对这段代码的运行方式感到困惑。

在命令行中,如果我输入python,然后在python环境中输入import test.py,我会得到预期的行为:

Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information.

>>>import test
i am cow
<multiprocessing.managers.SyncManager object at 0x025209B0>
i am cowboy 
>>>

但是,如果我在命令行输入test.py,我会得到

i am cow
i am cow
i am cow
i am cow
i am cow
i am cow
i am cow
i am cow
i am cow
i am cow
i am cow
i am cow
i am cow
i am cow
i am cow
i am cow
i am cow
i am cow

除非我杀了它,否则这大概会永远持续下去。当我杀死它时,我得到了一堆重复的错误:

KeyboardInterrupt
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Python27\lib\multiprocessing\forking.py", line 373, in main
    prepare(preparation_data)
  File "C:\Python27\lib\multiprocessing\forking.py", line 488, in prepare
    '__parents_main__', file, path_name, etc
KeyboardInterrupt
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Python27\lib\multiprocessing\forking.py", line 373, in main
    prepare(preparation_data)
  File "C:\Python27\lib\multiprocessing\forking.py", line 488, in prepare
    '__parents_main__', file, path_name, etc
KeyboardInterrupt

那么发生了什么?为什么它在导入时以一种方式运行,而当我尝试运行它时又以另一种方式运行?

【问题讨论】:

    标签: python import multiprocessing importerror python-multiprocessing


    【解决方案1】:

    multiprocessing won't work properly 在 Windows 上的交互式提示中,因为它无法在它产生的子进程中正确重新导入 __main__。然而,这实际上帮助你,因为它可以防止manager = mp.Manager() 行在Manager 启动时产生的子进程中递归执行。

    然而,在实际脚本中,孩子可以正确地重新导入__main__。您看到了无限递归,因为您没有使用 if __name__ == "__main__": 保护来保护对 mp.Manager() 的调用,即 required on Windows 以防止在重新导入发生时在子级中执行 mp.Manager()

    import multiprocessing as mp
    if __name__ == "__main__":
        manager = mp.Manager()
        print manager
    

    编辑:

    您的示例,您的主脚本 (test.py) 导入创建 Manager 的模块,需要进行一些重构。您需要通过调用模块中实际使用multiprocessing 的方法,从主脚本中实例化Manager

    print 'i am cow'
    import multi4
    if __name__ == "__main__":
        multi4.init_manager()
    print 'i am cowboy'
    

    multi4.py

    import multiprocessing as mp
    manager = None
    def init_manager():
        global manager
        manager = mp.Manager()
    

    这是确保仅在实际执行脚本时才创建 Manager 的唯一方法。

    【讨论】:

    • 不过有一点——我如何确定multi4.py 中的代码实际上正在执行?管理器对象没有打印到终端,当我更改为if name == 'multi4': 时,我在命令行调用test.py 时得到与以前相同的递归行为...
    • @Wapiti 啊,对,我最初错过了这个。您需要稍微重构您的脚本,以便通过在 test.py 中的 if __name__ == "__main__": 守卫中进行调用来实例化 Manager。我已经编辑了我的答案。
    • 好的,上面的代码肯定是在创建管理器,如果我嵌入打印命令就可以看到。但是,它也会产生 两次 的打印命令。我不明白为什么。你有同样的行为吗?它打印i am cow i am cow i am cowboy i am cowboy
    • 这似乎是一个 Windows 问题。在 Mac 上,它只打印牛和牛仔一次。
    • @Wapiti 哦,这是因为__main__ 模块(test.py)被重新导入到子模块中,这意味着该模块顶层的所有内容都被执行了两次;一次在父母身上,一次在孩子身上。只需移动 if __name__ == "__main__": 防护内的指纹即可修复它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-17
    • 1970-01-01
    • 1970-01-01
    • 2016-02-26
    • 2018-06-19
    相关资源
    最近更新 更多