2016-07-18 85 views
3

我想訪問在子進程中運行的python程序的回溯。子進程子追蹤

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!") 

內容:

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

如果我跑my_main_program.py,我得到以下錯誤:

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

Doc說「在新程序開始執行之前」,在你的情況下,新程序執行時引發了異常,因此沒有'child_traceback'。一旦新程序運行,您需要捕獲'CalledProcessError'異常,並執行以下操作:http://stackoverflow.com/questions/24849998/how-to-catch-exception-output-from-python-subprocess-check使用'CalledProcessError.output'輸出 – mguijarr

+0

在我的示例中,'CalledProcessError.output'只捕獲標準輸出,但不捕獲異常的回溯。 – schreon

+0

這可能是因爲輸出是在'stderr'上發送的。看看我給你的問題上面的鏈接的答案更多詳細信息 – mguijarr

回答

0

當您啓動另一個Python進程時,您還可以嘗試使用Python模塊multiprocessing;由子類的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

實際上'multiprocessing'在POSIX平臺上執行'os.fork',所以它不是一個新的虛擬環境;但是你可以通過儘早啓動'Process'對象來限制進程之間的共享數據量,這可能足夠滿足你的需求 – mguijarr

+0

如果你正在做一種調度器,爲什麼不使用[Celery](http:///www.celeryproject.org/) – mguijarr