【问题标题】:Catching python subprocess exception捕获python子进程异常
【发布时间】:2015-01-06 01:30:48
【问题描述】:

我有一个 python 脚本,我正在使用下面的子进程调用另一个脚本。

        sp = subprocess.Popen("script.py --arg1 --arg2', cwd=GIVEN_PATH, shell=True, stdout=subprocess.PIPE,  stderr=subprocess.STDOUT)

        while sp.poll() is None:
            for out in iter(sp.stdout.readline,''):
                self.log(out.rstrip())

这对我来说很好,但我想从 script.py 中获取任何异常。我知道我们可以获取 retcode 但我实际上需要获取完整的异常信息。

如果 script.py 引发

         raise IOERROR("got an exception")

那么我需要知道这些信息。我们获取 sys.exc_info() 等的类似方式。

有什么办法可以做到吗?

提前致谢

【问题讨论】:

  • 除了下面的答案之外,需要注意的是Python可以直接调用其他python模块,而不需要子进程,这将允许您捕获异常。这是你在这种情况下应该做的。

标签: python exception-handling subprocess


【解决方案1】:

不,您无法从子进程中获取 sys.exc_info() - 当您能够看到返回代码时,子进程的内存中的对象(包括堆栈跟踪)已经消失了。

您可以通过为 stderr 输出提供一个单独的管道并读取它来解析您的子进程写入 stderr 的文本。假设您的程序永远不会写入 stderr,否则该流中将显示的唯一文本将是错误消息和堆栈跟踪。

不过,您需要谨慎使用这种方法,因为如果进程向 stderr 写入的文本多于您可以缓冲的文本,您将陷入死锁。最好的解决方案是有一个单独的线程来并行读取 stdout 和 stderr。

【讨论】:

    【解决方案2】:

    如果您想获得sys.exc_info(),那么您可以导入模块并从中运行函数,而不是使用subprocess 模块。如果您需要在不同的进程中运行,可以使用multiprocessing 模块。

    另一种可能性是使用execfile() 将模块作为脚本在与父脚本相同的进程中运行。如果您想将命令行参数传递给脚本,那么您可以在调用execfile() 之前操作sys.argv 全局列表。

    或者您可以结合subprocess + execfile 方法:编写一个使用execfile 运行子脚本并序列化所有异常的包装脚本(例如,使用pickle)并使用@987654332 运行包装脚本@ 在您的父脚本中。单独捕获 stderr,以便能够 unpickle 孩子的异常信息。

    【讨论】:

    • 谢谢。唯一的问题是我需要使用 execfile() 上无法看到的参数运行 python 文件
    • @user2891472:我已经更新了答案以提及如何将命令行参数传递给使用execfile()开始的脚本
    猜你喜欢
    • 2017-12-29
    • 2011-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    • 2021-01-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多