子进程子回溯

sch*_*eon 5 python subprocess traceback

我想访问在子进程中运行的 python 程序的回溯。

文档说:

在新程序开始执行之前,子进程中引发的异常将在父进程中重新引发。此外,异常对象将有一个名为 child_traceback 的额外属性,它是一个字符串,包含从孩子的角度来看的回溯信息。

内容my_sub_program.py

raise Exception("I am raised!")
Run Code Online (Sandbox Code Playgroud)

内容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
Run Code Online (Sandbox Code Playgroud)

如果我运行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'
Run Code Online (Sandbox Code Playgroud)

如何在不修改子流程程序代码的情况下访问子流程的回溯?这意味着,我想避免try/except在我的整个子程序代码周围添加一个大子句,而是从我的主程序中处理错误日志。

编辑: sys.executable应该可以用不同于运行主程序的解释器替换。

mgu*_*arr 0

当你开始另一个Python进程时,你也可以尝试使用multiprocessingPython模块;通过对类进行子类化,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
Run Code Online (Sandbox Code Playgroud)

诀窍是让目标函数执行 Python 子程序,这是通过使用functools.partial.