Pythonマルチプロセッシングを試みるWindowsでのRuntimeError


122

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

編集:ちなみに、このコードは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 __name__ == '__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 __name__ == 'parallelTestModule':    #This didnt work
#        if __name__ == '__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()

@doctorlove私はそれをpython testMain.pyとして実行します
NGアルゴ

1
確かに
-if

1
@NGAlgo pymongoとマルチプロセッシングの問題をデバッグしている間、スクリプトは非常に役に立ちました。ありがとう!
クレイ

回答:


173

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

変更testMain.py

import parallelTestModule

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

3
(彼の手のひらを額にぶつけて)どー!できます!!!!どうもありがとうございます!再インポートされるのは元のメインモジュールであるという事実がありませんでした。この間ずっと、プロセスを起動する直前に" name =="チェックを試みていました。
NGアルゴ2013

1
'parallelTestModule'をインポートできないようです。Python 2.7を使用しています。そのまま使用できますか?
Jonny、2016年

2
@Jonny parallelTestModule.pyのコードは質問の一部です。
Janne Karila、2016年

1
@DeshDeepSinghコードスニペットは、スタンドアロンの例ではありません。それはOPのコードの修正です
Janne Karila

1
@DeshDeepSinghそのモジュールは質問の一部です。
Janne Karila、

25

testMain.pyのメイン関数内にコードを配置してみてください

import parallelTestModule

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

ドキュメントを参照してください:

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

言う

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

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


9

以前の答えは正しいですが、注意するのに役立つ小さな複雑さがあります。

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

if __name__ ==  '__main__':
  import my_module

3

@Oferが言ったように、別のライブラリまたはモジュールを使用している場合、それらのすべてを if __name__ == '__main__':

だから、私の場合、このように終わりました:

if __name__ == '__main__':       
    import librosa
    import os
    import pandas as pd
    run_my_program()

0

私の場合、それはコードの単純なバグであり、作成前に変数を使用していました。上記の解決策を試す前に確認する価値があります。なぜこの特定のエラーメッセージが表示されたのですか、主は知っています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.