如果从没有主保护(if __name__ == '__main__':
)的脚本导入模块,在模块中的某个函数中执行任何类型的并行操作都将导致Windows上的无限循环。每个新进程加载所有源,现在__name__
不等于'__main__'
,然后继续并行执行。如果没有主保护,我们将在每个新进程中对同一个函数进行另一次调用,从而产生更多的进程,直到崩溃。这只是Windows上的一个问题,但是脚本也可以在osx和linux上执行。在
我可以通过写入磁盘上的一个特殊文件来检查这一点,并从中读取以查看我们是否已经开始,但这限制了我们一次只能运行一个python脚本。修改所有调用代码以添加主保护的简单解决方案是不可行的,因为它们分布在许多存储库中,而我无权访问这些存储库。因此,我希望在使用主保护的情况下进行并行化,但在不使用的情况下,我将回退到单线程执行。在
如何判断在导入循环中是否由于缺少主保护而被调用,以便可以回退到单线程执行?在
下面是一些演示代码:
带并行代码的库:
from multiprocessing import Pool
def _noop(x):
return x
def foo():
p = Pool(2)
print(p.map(_noop, [1, 2, 3]))
好进口商(有警卫):
^{pr2}$不良进口商(无防护):
from lib import foo
foo()
如果错误的导入程序因此运行时错误而失败,一次又一次:
p = Pool(2)
File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\context.py", line 118, in Pool
context=self.get_context())
File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\pool.py", line 168, in __init__
self._repopulate_pool()
File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\pool.py", line 233, in _repopulate_pool
w.start()
File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\process.py", line 105, in start
self._popen = self._Popen(self)
File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\context.py", line 313, in _Popen
return Popen(process_obj)
File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\popen_spawn_win32.py", line 34, in __init__
prep_data = spawn.get_preparation_data(process_obj._name)
File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\spawn.py", line 144, in get_preparation_data
_check_not_importing_main()
File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\spawn.py", line 137, in _check_not_importing_main
is not going to be frozen to produce an executable.''')
RuntimeError:
An attempt has been made to start a new process before the
current process has finished its bootstrapping phase.
This probably means that you are not using fork to start your
child processes and you have forgotten to use the proper idiom
in the main module:
if __name__ == '__main__':
freeze_support()
...
The "freeze_support()" line can be omitted if the program
is not going to be frozen to produce an executable.
因为您使用的是
multiprocessing
,所以您还可以使用它来检测您是主进程还是子进程。但是,这些特性没有文档化,因此只是实现细节,在python版本之间可能会发生更改而不发出警告。在每个进程有一个}。你可以检查他们中的任何一个,看看你是否在主进程中。在主过程中},而{}将是{})。在
name
、_identity
和{name
将是'MainProcess'
,_identity
将是{我的解决方案允许您继续使用
multiprocessing
,但只修改子进程,使它们不能永远创建子进程。它使用修饰符将foo
更改为子进程中的no-op,但在主进程中返回foo
不变。这意味着当派生的子进程尝试执行foo
时,不会发生任何事情(就像它是在__main__
保护中执行的一样)。在相关问题 更多 >
编程相关推荐