我在一个子流程中执行的代码本应引发异常。
当从子流程返回异常时(最好是在保留堆栈跟踪的情况下),我想在主流程中引发相同的异常,但我不确定如何做到这一点。
我从子流程中捕获stderr很好,但我找不到如何解析它,所以我得到了异常的类型。我该如何做到这一点?
我正在使用python 2.7
主要方法
import subprocess
example=subprocess.Popen(["python","example.py"],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
return_obj, return_error = example.communicate()
if return_error:
# replace with error from subprocess
print "Should raise ",NameError('HiThere')
raise TypeError('Wrong type')
子流程
raise NameError('HiThere')
如果您只想让python代码在单独的进程中运行,那么您可能不应该使用subprocess
。正如Serge Ballesta所说,subprocess
的目的是在操作系统级别运行一个不同的程序,而不必特别关心它是什么——没有什么可以帮助你正确处理python解释器过程的复杂性。
出于这种目的,最好简单地import
您的代码并使用multiprocessing
,它公开了一个高级接口来帮助您在多个进程中运行python代码。
假设您在example.py
:上有一个定义良好的main
函数
from examply import main as example_main
import multiprocessing
pool= multiprocessing.Pool(1)
pool.apply( example_main )
使用此代码,异常和返回值都将透明地提供给主进程。
如果您不想阻止等待结果,也可以使用Pool.apply_async
。
子流程执行不同的本机应用程序。它可以是java、C++、lisp,甚至Fortran或Cobol。因此,只有两种方法可以从Python子流程中获取异常:
- 完全忘记子流程,直接在同一个python程序中调用python代码,只需简单的
try except
即可完成工作 - 在主进程和子进程之间的接口契约中定义,例如,如果没有发生致命的exeption,则要求错误输出必须为空,否则包含异常和堆栈争用的pickle
如果两个进程都是python进程,并且必须使用管道,则可以通过管道序列化异常对象。
来电者:
parent_conn.send(event)
result = parent_conn.recv()
if isinstance(result, Exception):
raise result
else:
return result
接收器:
def subprocess_loop(parent_conn, child_conn):
parent_conn.close()
while True:
event = child_conn.recv()
try:
result = event_handler(event)
except Exception as exc:
child_conn.send(exc)
continue
child_conn.send(result)
接收器进程创建:
parent_conn, child_conn = Pipe()
process = Process(target=subprocess_loop, args=(parent_conn, child_conn))
process.start()
child_conn.close()