2016-07-18 52 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