2016-08-10 13 views
0

ロジックはかなり次のようなものです:Pythonのマルチプロセッシング - 正常な終了未処理の例外が発生したときのプロセスで例外を処理しようとする私のマルチプロセッシングプログラムの

import multiprocessing 

class CriticalError(Exception): 

    def __init__(self, error_message): 
     print error_message 
     q.put("exit") 


def foo_process(): 
    while True: 
     try: 
      line = open("a_file_that_does_not_exist").readline() 
     except IOError: 
      raise CriticalError("IOError") 

     try: 
      text = line.split(',')[1] 
      print text 
     except IndexError: 
      print 'no text' 

if __name__ == "__main__": 
    q = multiprocessing.Queue() 
    p = multiprocessing.Process(target=foo_process) 
    p.start() 

    while True: 
     if not q.empty(): 
      msg = q.get() 
      if msg == "exit": 
       p.terminate() 
       exit() 

私が試し-除いを持っていない場合ファイル操作の前後に、私は

Traceback (most recent call last): 
    File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap 
    self.run() 
    File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run 
    self._target(*self._args, **self._kwargs) 
    File "foo.py", line 22, in foo_process 
    line = open("a_file_that_does_not_exist").readline() 
IOError: [Errno 2] No such file or directory: 'a_file_that_does_not_exist' 

を受け取りますが、プログラムは開いたままです。 IOErrorに関連するtry-except 節を削除するPythonの方法がありますか、実際にはすべての未処理の例外を持つことがありますか キュー "q"に "exit"メッセージを入れるか、またはプロセスを終了して プログラムを終了してください方法?これは、私が マルチプロセスのないアプリケーションでプログラムを自動的に終了させるエラーを捕捉する必要がないときに私のコードベースを大量にクリアするでしょう。 また、AssertionErrorが プログラムを終了するときにアサーションを追加することもできます。解決策が何であれ、 トレースバックが表示されるようにしたいと考えています。私の現在の解決策はそれを提供していません。

答えて

0

とにかく子どもが死にます(つまり、p.terminate()は無意味です)ので、子プロセスがまだ生きているかどうかをマスタープロセスに確認させてください。

from queue import Empty 
# from Queue import Empty # if Python 2.x 

while not q.empty(): 
    if not p.is_alive(): 
     break 

    try: 
     msg = q.get(timeout=1) 
    except Empty: 
     continue 

    # other message handling code goes here 

# some graceful cleanup 
exit() 

子供が死んでいるとき、それは永遠にブロックされませんので、私はgetにタイムアウトを追加しました注意してください。必要に応じて期間をカスタマイズすることができます。

これで、エラー時にキューにプッシュするような子プロセスでは何もする必要はありません。それに加えて、元のアプローチはいくつかのまれなケースで失敗するでしょう。子を強制終了すると、マスターは永遠にハングします(子がキューに何かを押し込む時間がないため)。

あなたは潜在的に(どちらかの親のstdoutまたはファイルまたは任意のファイルディスクリプタのサポートに)foo_process関数の内部sys.stdout(および/またはsys.stderr)を再結合して、子プロセスからのトレースバックを取得することができます。ここを見て:キューなしと私はそのような何かのために行くだろう、複数のプロセスと

Log output of multiprocessing.Process


processes = [f, b, c] 
while processes: 
    time.sleep(1) 
    for p in processes: 
     if not p.is_alive(): 
      processes.remove(p) 
      break 
exit() 

とのより良い行うことができます結合します

processes = [f, b, c] 
for p in processes: 
    p.join() 
exit() 

マスターがwaiの間に何か他のことをすることは想定されていないと仮定します子供のためのティン。

+0

子供が生きているかどうかを確認することは素晴らしい考えです。キューはメッセージ以外のものを配信しないので、必要ではありません(ソリューションがキューをチェックしている他の理由があるかどうかわかりません)。私は、複数のプロセスがあると述べていたはずです。しかし、私はループ内の各プロセスに対して 'is_alive'を照会し、いずれかが死んでいる場合、終了する前に他のプロセスを強制終了しました。トレースバックを出力して正常に終了します:http://pastebin.com/K1C9TbNY – maqp

+0

@maqpプロセスのリストを保存し、それらが 'for'ループで生存しているかどうかを調べることができます。また、キューを削除することも大きな利点です。しかし、その場合、おそらく 'busy_wait '(https://en.wikipedia.org/wiki/Busy_waiting)を避けるために' time.sleep() 'が必要になるでしょう。 – freakish

+0

(はい、遅延を使用していますが、サンプルコードを最小限に抑えるためにそれらを残しました)。どうもありがとう! – maqp

関連する問題