メインガード(if __name__ == '__main__':
)を使用せずにスクリプトからモジュールをインポートした場合、モジュールの一部の機能で並列処理を行うと、Windowsでは無限ループになります。新しいプロセスごとに、すべてのソースがロードされます(__name__
は'__main__'
と等しくない)。メインガードがなければ、クラッシュするまで、新しいプロセスのそれぞれで同じ機能を呼び出し、さらに多くのプロセスを呼び出すことになります。それはWindows上の唯一の問題ですが、スクリプトはosxとlinuxでも実行されます。メインガードのない関数から呼び出した場合の比較
私はこれをディスク上の特別なファイルに書き込んで確認し、すでに読み始めているかどうかを確認することができますが、一度に実行される単一のpythonスクリプトに制限されています。メインガードを追加するためのすべての呼び出しコードを変更する単純な解決策は、アクセスできない多くのリポジトリに広がっているため実行できません。したがって、メインガードが使用されている場合は並列化したいが、そうでない場合はシングルスレッド実行にフォールバックしたい。
メインガードがないためにインポートループで呼び出されているかどうかを確認して、シングルスレッド実行にフォールバックできるようにするにはどうすればよいですか?
ここではいくつかのデモコードです:並列コードと
のlib:
from multiprocessing import Pool
def _noop(x):
return x
def foo():
p = Pool(2)
print(p.map(_noop, [1, 2, 3]))
(ガード付き)グッド輸入:(ガードなし)
from lib import foo
if __name__ == "__main__":
foo()
悪い輸入:
はfrom lib import foo
foo()
012悪い輸入者が何度も何度も、この例外RuntimeErrorで失敗し
:
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.
を実行しようとしたときに、[最小の例]を作成してくださいできることを意味しますhelp/mcve)?プロセスを生成するために使用した戦略/モジュール(['subprocess')(https://docs.python.org/library/subprocess.html)、[ (https://docs.python.org/library/multiprocessing.html)、['os.spawn'](https://docs.python.org/3/library/os.html#os。 spawnl))? – metatoaster
これは 'multiprocessing'です:) –