【问题标题】:Python subprocess stderr redirection, redirect warnings, still raise on control flow stoppers?Python子进程stderr重定向,重定向警告,仍然引发控制流停止?
【发布时间】:2013-06-06 07:49:21
【问题描述】:

我进行了基本的尽职调查,但在任何地方都找不到一个好的答案。

我想调用 subprocess.Popen,当控制流被中断时它们仍然会引发 Python 异常,但我想同时重定向 stderr。

该用例用于不应输出警告但其内部逻辑仍想了解子进程问题的命令行客户端。

例如,这会静默重定向所有错误:

subprocess.Popen(command, stderr=subprocess.PIPE)

将 Python 模块作为带有内容的子进程调用:

raise(Exception("AVAST!"))

不会引发任何事情。

如果它重定向所有错误文本,但仍然会引发任何过早停止控制流的事情,那就太好了。我是否需要使用返回码并希望我调用的所有子流程都正确实现了这一点?

到目前为止我想到的最好的事情是手动解析重定向的错误,在我看来这是一个非常糟糕的实现。

有没有一种干净规范的方法来做到这一点?

【问题讨论】:

    标签: python exception subprocess stderr


    【解决方案1】:

    没有办法通过像 stderr 这样的文本管道传递异常,因为你可以通过文本管道传递的只是文本。

    但是有几个选择:

    1. 确保您的所有孩子在异常时都以非零状态退出(这是默认设置,如果您不执行任何操作)并且在任何其他情况下都不要这样做(除非您想要处理某些情况与例外相同)。
    2. 解析stderr 中的异常。
    3. 为父母和孩子创建一些其他的交流渠道来分享。
    4. 不要使用subprocess。例如,如果您通过 subprocess 运行 Python 脚本的唯一原因是为了获得核心并行性(或内存空间隔离),那么使用 multiprocessingconcurrent.futures 可能会容易得多,它们已经构建了为您传播异常的机制。

    来自您的评论:

    我的用例是调用一堆非 Python 第三方的东西。如果返回码是标准库模块传播错误的方式,我很乐意使用它们。

    不,Python 标准库使用Exceptions 传播错误。你也应该这样。

    返回码是非 Python 第三方事物传播错误的方式。 (实际上,它们是如何传播错误和意外信号的,但是……不用担心。)这仅限于 7 位的数据,而且含义并没有真正标准化,所以它不是那么好。但这就是 POSIX 子进程模型中的所有内容,所以这就是通用程序所使用的。

    您可能想做的与subprocess.check_call 所做的相同——如果返回码不为零,则引发异常。 (事实上​​,如果你没有做任何异步操作,首先问问自己是否可以使用check_call,而不是显式使用Popen 对象。)

    例如,如果您这样做:

    output, errors = p.communicate()
    

    改成这样:

    output, errors = p.communicate()
    if p.returncode:
        raise subprocess.CalledProcessError(p.returncode, 'description')
    

    (描述通常是子进程路径或名称。)

    然后,您的其余代码就可以处理异常了。

    【讨论】:

    • 感谢@Abernert 的回复。我的用例是调用一堆非 Python 第三方的东西。如果返回码是标准库模块传播错误的方式,我很乐意使用它们。我去浏览一下。
    • 您的回复有点混乱。让我编辑我的答案以更好地解释。
    • 这是有道理的。可能以下是混乱的根源? 2,3,4 并不是非常有吸引力的选项,因为开发过程存在一些限制,为了简洁我将省略这些限制。对于 1,我担心的是即使发生错误,我调用的某些东西也可能返回 0,并且 Python 可能会使用其他方法来确定失败并引发异常。我的评论是在打算重定向 err 的上下文中编写的,然后检查返回码并在它不是 0 的情况下引发异常。我当然可以更清楚地问 Python 是否只使用 rc。
    • 看起来不错。传播绝对是在那里使用的错误词。我原本打算传达的是对 Python 如何确定给定子进程以需要引发异常的方式出错的好奇心。我希望我的使用符合规范而不是滚动我自己的逻辑,并且看起来检查返回码会是什么?
    • 该术语的不正确性来自我希望引用从子流程到 Python 错误处理的单个错误步骤而不是对错误/异常的整个路径的引用。跨度>
    猜你喜欢
    • 2012-07-14
    • 2015-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-25
    • 1970-01-01
    • 2013-07-22
    相关资源
    最近更新 更多