【问题标题】:Reraise exception from subprocess从子进程重新引发异常
【发布时间】:2014-11-28 09:52:58
【问题描述】:

我在一个应该引发异常的子进程中执行代码。

我想在子进程返回异常时在主进程中引发相同的异常(最好在保留堆栈跟踪的同时),但我不知道该怎么做。

我很好地从子进程中捕获了标准错误,但我找不到如何解析它,所以我得到了异常的类型。我将如何做到这一点?

我正在使用 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')

【问题讨论】:

  • 如果不重新解析异常并抛出新异常,我认为您无法获得信息
  • 您应该考虑importing 而不是运行另一个解释器。请注意,如果您这样做,您仍然可以在单独的进程中运行 example.py 中的任何函数。
  • if return_error: raise Exception, return_error
  • 您可能希望execfile() 在同一进程中运行 example.py 脚本,以便轻松将异常作为对象获取。

标签: python python-2.7 exception subprocess


【解决方案1】:

如果你只想让你的 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

【讨论】:

  • 我的情况是我的程序接受标准输入并且在某个输入上它应该崩溃。我正在使用 subprocess 来测试这种行为。是否可以为此使用多处理?
  • @Bomaz 这是可行的,但很古怪 - 请参阅 programming guidelines 部分替换 stdin。简单地重写example.py 以接受带有文件文件对象的可选参数并从测试程序传递它可能要容易得多。
  • @Bomaz 或者使用multiprocessingbuilt-in communication mechanisms,比如管道
【解决方案2】:

子进程执行不同的本机应用程序。它可以是 java、C++、lisp 甚至是 Fortran 或 Cobol。所以你只有两种方法可以从 Python 子进程中获取异常:

  • 完全忘记子进程,直接在同一个python程序中调用python代码,简单try except就可以了
  • 在主进程和子进程之间的接口契约中定义,例如,如果没有发生致命异常,则要求错误输出必须为空,否则包含异常和堆栈跟踪的pickle。

【讨论】:

    猜你喜欢
    • 2012-01-13
    • 1970-01-01
    • 1970-01-01
    • 2011-09-12
    • 2017-10-05
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多