web-dev-qa-db-ja.com

subprocess.wait()はPopenプロセスの終了を待機していません(スレッドを使用している場合)?

subprocess.Popen()を使用して、同じアプリケーションの複数のインスタンスを自分のpythonスクリプトを使用して同時に実行するスクリプトから生成します。いくつかの問題が発生します。各スレッドでアプリケーションを実行します。 popen()呼び出しを使用し、callingwait()で終了するのを待ちます。問題は、wait()- callが実際にプロセスを終了します。1つのスレッドのみを使用し、プロセスの開始時と終了時にテキストメッセージを出力して実験しました。したがって、スレッド関数は次のようになります。

_def worker():
    while True:
        job = q.get() # q is a global Queue of jobs
        print('Starting process %d' % job['id'])
        proc = subprocess.Popen(job['cmd'], Shell=True)
        proc.wait()
        print('Finished process %d' % job['id'])
        job.task_done()
_

ただし、使用するスレッドが1つだけの場合でも、「Finished process ...」メッセージが表示される前に、いくつかの「Starting process ...」メッセージが出力されます。 wait()が実際に待機しない場合はありますか?いくつかの異なる外部アプリケーション(C++コンソールアプリケーション)があり、同時に複数のインスタンスが実行されます。それらの一部では私のコードは機能しますが、他の場合は機能しません。 wait()の呼び出しに何らかの影響を与える外部アプリケーションに問題があるのでしょうか?スレッドを作成するためのコードは次のようになります。

_for i in range(1):
    t = Thread(target=worker)
    t.daemon = True
    t.start()
q.join() # Wait for the queue to empty
_

pdate 1:一部の外部アプリケーションでは、-1073471801の戻りコード(_proc.returncode_)が表示されることもあります。たとえば、外部アプリケーションの1つがその戻りコードに最初の2回Popenが呼び出されるが、最後の2つは呼び出されない(4つのジョブがある場合)。

pdate 2:明確にするために、現在、キューに4つのジョブがあり、4つの異なるテストケースがあります。コードを実行すると、外部アプリケーションの1つで、最初の2つのPopen- callsが戻りコード-1073471801を生成します。しかし、Popenが呼び出す正確なコマンドを出力してコマンドウィンドウで実行すると、問題なく実行されます。

解決済み!自分が抱えていた問題をなんとか解決しました。問題は、スレッドプログラミングの経験の欠如にあったと思います。最初のワーカースレッドを作成したとき、pythonスクリプトが終了するまで、それらは存続し続けるという事実を逃しました。誤って、キューに新しいアイテムを置くたびに、より多くのワーカースレッドを作成しました(実行する外部プログラムごとにバッチで実行します。)したがって、4番目の外部アプリケーションに到達するまでに、1つしかないと思っていたとしても、4つのスレッドが同時に実行されていました。

19
iceaway

Popenの代わりに check_call() を使用することもできます。 check_call()は、Shell=Trueし、ジョブの終了コードを返します。

13
Nick

悲しいことに、Shell=Trueを使用してサブプロセスを実行すると、 wait( は、コマンドshではなく、cmdサブプロセスが完了するまで待機します。

Shell=Trueを使用できない場合は、このようにプロセスグループを作成できます answer を使用して os.waitpid を使用することをお勧めしますシェルプロセスだけでなく、プロセスグループを待機します。

これがお役に立てば幸いです:)

9
mouad

私も問題を抱えていましたが、あなたの影響を受けました。

鉱山は次のように見え、美しく機能します。

    startupinfo = subprocess.STARTUPINFO()
    startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW
    startupinfo.wShowWindow = subprocess.SW_HIDE
    proc = subprocess.Popen(command, startupinfo=startupinfo)
    proc.communicate()
    proc.wait()

これもウィンドウを非表示にしていることに注意してください。

0
alfadog67

呼び出しているすべてのアプリケーションに、終了時に有効なシステム戻りコードがあることを確認してください。

0
Chakib