0

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

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

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

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

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

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

raise(Exception("AVAST!"))

不提出任何东西。

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

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

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

4

1 回答 1

1

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

但是有几个选择:

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

从您的评论中:

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

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

返回码是非 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')

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

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

于 2013-06-05T19:28:13.233 回答