2016-07-18 3 views
3

サブプロセスの子トレースバック

The documentationは言う:my_sub_program.py

Exceptions raised in the child process, before the new program has started to execute, will be re-raised in the parent. Additionally, the exception object will have one extra attribute called child_traceback, which is a string containing traceback information from the child’s point of view.

内容:my_main_program.py

raise Exception("I am raised!") 

内容:私はmy_main_program.pyを実行すると、私は次のエラーを取得する

import sys 
import subprocess 
try: 
    subprocess.check_output([sys.executable, "my_sub_program.py"]) 
except Exception as e: 
    print e.child_traceback 

Traceback (most recent call last): 
    File "my_main_program.py", line 6, in <module> 
    print e.child_traceback 
AttributeError: 'CalledProcessError' object has no attribute 'child_traceback' 

どのように私は、サブプロセス・プログラム・コードを変更せずにサブプロセスのトレースバックにアクセスすることができますか?これは、サブプログラムコード全体に大きなtry/except句を追加することを避けたいのではなく、メインプログラムからのエラーログを処理することを意味します。

編集:sys.executableは、メインプログラムを実行するインタープリタとは異なるインタープリタで置き換える必要があります。

+0

ドクは「新しいプログラムが実行を開始する前に、」新しいプログラムが実行された一方で、あなたのケースで例外が、それ故に何の 'child_traceback'を提起しなかったと言います。新しいプログラムが実行されると、 'CalledProcessError'例外をキャッチして、次のようにする必要があります:http://stackoverflow.com/questions/24849998/how-to-catch-exception-output-from-python-subprocess-check -output 'CalledProcessError.output'を使用した出力 – mguijarr

+0

私の例では、 'CalledProcessError.output'は標準出力だけをキャプチャしましたが、Exceptionのトレースバックはキャプチャしませんでした。 – schreon

+0

これは、出力が 'stderr'で送られたためです。 – mguijarr

答えて

0

あなたは別のPythonのプロセスを開始しているとして、あなたはまた、multiprocessing Pythonモジュールを使用しようとすることができます。対象関数から例外を取得するのはとても簡単ですサブクラス化Processクラスによって:

from multiprocessing import Process, Pipe 
import traceback 
import functools 

class MyProcess(Process): 
    def __init__(self, *args, **kwargs): 
     Process.__init__(self, *args, **kwargs) 
     self._pconn, self._cconn = Pipe() 
     self._exception = None 

    def run(self): 
     try: 
      Process.run(self) 
      self._cconn.send(None) 
     except Exception as e: 
      tb = traceback.format_exc() 
      self._cconn.send((e, tb)) 
      # raise e # You can still rise this exception if you need to 

    @property 
    def exception(self): 
     if self._pconn.poll(): 
      self._exception = self._pconn.recv() 
     return self._exception 


p = MyProcess(target=functools.partial(execfile, "my_sub_program.py")) 
p.start() 
p.join() #wait for sub-process to end 

if p.exception: 
    error, traceback = p.exception 
    print 'you got', traceback 

トリックはPythonのサブプログラムを実行するターゲット機能を持つことで、これはfunctools.partialを使用して行われます。

+0

このソリューションは、サブプロセスがメインプログラムとは異なるインタプリタで実行できるようにしていますか?あなたの提案を見ると、私の例では 'sys.executable'を使うのは間違いでした。しかし、私の質問の文脈では、メインプロセス以外の仮想環境でスクリプトを起動する必要があります。 (メインプロセスはある種のスケジューラーになります) – schreon

+0

実際に 'マルチプロセッシング'はPOSIXプラットフォームで 'os.fork'を実行するので、新しい仮想環境ではありません。しかし、プロセス間で共有されるデータの量を制限することができます。プロセスオブジェクトを早期に起動することで、あなたのニーズに十分に合っているかもしれません。 – mguijarr

+0

[Celery](http: /www.celeryproject.org/) – mguijarr

関連する問題