web-dev-qa-db-ja.com

WindowsでのRuntimeError python multiprocessing

私は、Windowsマシンでスレッディングとマルチプロセッシングを使用する初めての正式なpythonプログラムを試しています。 pythonで次のメッセージが表示されますが、プロセスを起動できません。問題は、mainモジュールでスレッドを起動していないことです。スレッドは、クラス内の別のモジュールで処理されます。

[〜#〜] edit [〜#〜]:ところで、このコードはubuntuで問題なく実行されます。かなり窓の上ではない

RuntimeError: 
            Attempt to start a new process before the current process
            has finished its bootstrapping phase.
            This probably means that you are on Windows and you have
            forgotten to use the proper idiom in the main module:
                if __== '__main__':
                    freeze_support()
                    ...
            The "freeze_support()" line can be omitted if the program
            is not going to be frozen to produce a Windows executable.

私の元のコードはかなり長いですが、コードの短縮バージョンでエラーを再現することができました。これは2つのファイルに分割されます。最初のファイルはメインモジュールであり、プロセス/スレッドを処理してメソッドを呼び出すモジュールをインポートすること以外はほとんど行いません。 2番目のモジュールは、コードの中身です。


testMain.py:

import parallelTestModule

extractor = parallelTestModule.ParallelExtractor()
extractor.runInParallel(numProcesses=2, numThreads=4)

parallelTestModule.py:

import multiprocessing
from multiprocessing import Process
import threading

class ThreadRunner(threading.Thread):
    """ This class represents a single instance of a running thread"""
    def __init__(self, name):
        threading.Thread.__init__(self)
        self.name = name
    def run(self):
        print self.name,'\n'

class ProcessRunner:
    """ This class represents a single instance of a running process """
    def runp(self, pid, numThreads):
        mythreads = []
        for tid in range(numThreads):
            name = "Proc-"+str(pid)+"-Thread-"+str(tid)
            th = ThreadRunner(name)
            mythreads.append(th) 
        for i in mythreads:
            i.start()
        for i in mythreads:
            i.join()

class ParallelExtractor:    
    def runInParallel(self, numProcesses, numThreads):
        myprocs = []
        prunner = ProcessRunner()
        for pid in range(numProcesses):
            pr = Process(target=prunner.runp, args=(pid, numThreads)) 
            myprocs.append(pr) 
#        if __== 'parallelTestModule':    #This didnt work
#        if __== '__main__':              #This obviously doesnt work
#        multiprocessing.freeze_support()        #added after seeing error to no avail
        for i in myprocs:
            i.start()

        for i in myprocs:
            i.join()
76
NG Algo

Windowsでは、サブプロセスは起動時にメインモジュールをインポート(実行)します。サブプロセスを再帰的に作成しないように、メインモジュールにif __== '__main__':ガードを挿入する必要があります。

変更されたtestMain.py

import parallelTestModule

if __== '__main__':    
    extractor = parallelTestModule.ParallelExtractor()
    extractor.runInParallel(numProcesses=2, numThreads=4)
107
Janne Karila

TestMain.pyのメイン関数内にコードを入れてみてください

import parallelTestModule

if __==  '__main__':
  extractor = parallelTestModule.ParallelExtractor()
  extractor.runInParallel(numProcesses=2, numThreads=4)

docs を参照してください:

"For an explanation of why (on Windows) the if __== '__main__' 
part is necessary, see Programming guidelines."

言う

「意図しない副作用(新しいプロセスの開始など)を引き起こすことなく、新しいPythonインタープリターによってメインモジュールを安全にインポートできることを確認してください。 "

... if __== '__main__'を使用して

19
doctorlove

以前の回答は正しいものの、発言するのに役立つ小さな問題があります。

メインモジュールが、グローバル変数またはクラスメンバー変数が定義され、新しいオブジェクトに初期化(または使用)されている別のモジュールをインポートする場合、同じ方法でインポートを調整する必要があります。

if __==  '__main__':
  import my_module
4
Ofer