【问题标题】:For subprocess.stderr=STDOUT - Is stdout=PIPE better than stdout="a_file_name"?对于 subprocess.stderr=STDOUT - stdout=PIPE 是否优于 stdout="a_file_name"?
【发布时间】:2016-02-29 21:45:29
【问题描述】:

[已编辑]
处理来自subprocess.Popen 的标准输出的两个选项是stdout="a_file_name"stdout=subprocess.PIPE
stderr 可以通过stderr=subprocess.STDOUT 与其中任何一个组合。

对于我目前正在做的事情(模糊测试),我生成的 stdout="a_file_name" 代码略短且更清晰。

但是,据我所见,stdout=PIPE 似乎经常受到其他人的青睐,但我不确定所有原因。

如果Popen([cmd, arg], ...) 中使用的cmd 是一个将错误输出写入stderr 的外部可执行文件,那么stdout=PIPE 是否比stdout="a_file_name" 更好?

各有什么优缺点?

  • 在我的特定上下文中(参见下面的代码 sn-ps),我可以看到使用 stdout=PIPE 而不是 stdout="a_file_name" 的一个优势是前者可以让我轻松跳过写入空文件。
  • 如果发生 cmd 崩溃,是否可能 2 个中的 1 个更有可能获得所有错误输出?

虽然我有自己的特定背景,但我也有兴趣了解更一般情况的答案。

为了更好地解释我的上下文,这里是我的 2 个替代代码段:

import subprocess
import sys

assert sys.version_info >= (3, 3)
    # timeout added for subprocess's wait() and communicate() in Python 3.3.

with open('sub_proc1.outerr', 'w') as f_outerr1:
    sub_proc1 = subprocess.Popen([cmd, args], stdout=f_outerr1,
                                 stderr=subprocess.STDOUT,
                                 universal_newlines=True)
    try:
        return_code = sub_proc1.wait(timeout=10)
        print('*** %s CRASHED with return code: %d.' % (cmd, return_code))
    except subprocess.TimeoutExpired:
        print('*** %s succeeded.' % cmd)
        sub_proc1.kill()

对比:

...
with open('sub_proc2.outerr', 'w') as f_outerr2:
    sub_proc2 = subprocess.Popen([cmd, args], stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT,
                                 universal_newlines=True)
    try:
        (sub_proc2_out, sub_proc2_err) = sub_proc2.communicate(timeout=10)
        print('*** %s CRASHED with return code: %d.' %
              (cmd, sub_proc2.poll()))
        assert sub_proc2_err is None
            # Since stderr was redirected to STDOUT, this should be None.
        f_outerr2.write(str(sub_proc2_out or ""))
            # Treat 'None' as an empty string).
    except subprocess.TimeoutExpired:
        print('*** %s succeeded.' % cmd)
        sub_proc2.kill()

原帖:

TITLE:子流程:stderr=STDOUT 与 stderr=PIPE 的优缺点?

处理来自 'subprocess.Popen' 似乎是 'stderr=STDOUT' (与 'stdout="some_file"') 和 'stderr=PIPE'。

对于我想做的事情(模糊测试),我得到的“stderr=STDOUT” 代码更短更简洁。

但是,根据我的阅读,“stderr=PIPE”似乎是 首选,但我不确定所有原因。

如果使用的“cmd”是写入错误输出的外部可执行文件 对于“stderr”,使用“stderr=STDOUT”的优缺点是什么 与“stderr=PIPE”相比?

...

【问题讨论】:

  • 如果您在测试程序中没有对输出(除了写入文件)做任何事情,我认为这两个代码之间没有太大区别。如果您想检查输出的实际细节(例如,将其包含在您的 print 调用中,或者检查它是否写出特定的字符串),那么使用 PIPE 将是必要的。第一个代码的一个可能优点是,如果正在运行的程序交替写入它们,它将为您交错 stdout 和 stderr 流。另一方面,您无法区分这两个输出!
  • 感谢您的有用评论,Blckknght。如果我想检查输出的实际细节,我可以看到 PIPE 将是更好的选择。在我的特定上下文中,交错的 stdout 和 stderr 流很好。
  • 您的评论让我意识到了一些我以前没有意识到的事情。这种交错可以使用任一方法进行:stdout="a_file_name", stderr=subprocess.STDOUT 或 stdout=subprocess.PIPE, stderr=subprocess.STDOUT 同样,使用任一方法也可以使 stdout 和 sterrr 流非交错:stdout ="file_name_1", stderr="file_name_2" 或 stdout=subprocess.PIPE, stderr=subprocess.PIPE
  • 因此,我更新了我的帖子及其标题以反映 2 个交错选项: - 新标题:对于 subprocess.stderr=STDOUT - stdout=PIPE 是否优于 stdout="a_file_name"?

标签: python subprocess stdout popen stderr


【解决方案1】:

写入特定文件意味着如果您的程序一次运行多次,则会发生冲突,因为两个进程都希望写入同一个文件。 (搜索与临时文件创建和安全漏洞有关的问题)

使用管道意味着不存在文件名唯一性问题。

你关心输出吗?如果没有,请使用subprocess.DEVNULL,它会为您丢弃输出。

【讨论】:

  • 感谢您的回答 dsh。我可以看到写入特定文件可能会导致名称冲突。不过,我的脚本会根据当前日期/时间将其所有输出写入子文件夹中,因此这对它来说应该不是问题:out_fdr = time.strftime(os.path.join('%Y', '%m', '%d', '%H.%M.%S')) 我确实关心输出。到目前为止,我已经从我的 .outerr 文件中获得了一些有用的信息,例如:Out of memory 或 Bogus memory allocation size
  • 如果它在同一秒内运行两次,您将在目录上发生名称冲突:)。如果您想保存输出以供将来使用,那么文件更合适。如果你想在程序中处理输出,那么管道更自然。
  • 这是一大优势。我的 PDF 模糊测试通常会在
猜你喜欢
  • 2012-03-25
  • 2011-10-25
  • 2020-01-24
  • 2015-09-01
  • 2011-01-06
  • 2014-11-18
  • 2015-01-01
  • 2011-10-04
  • 1970-01-01
相关资源
最近更新 更多