【问题标题】:subprocess.Popen() stdout and stderr handlingsubprocess.Popen() 标准输出和标准错误处理
【发布时间】:2018-10-23 00:41:15
【问题描述】:

我怎样才能处理一个进程stderr?

proc = subprocess.Popen('ll'.split(), stdout=subprocess.PIPE)

for i in proc.stdout:
   print(i)

现在我正在流式传输输出,但我不确定如何正确处理可能发生的潜在错误。

我想使用out, err = proc.communicate(),但我的out 可能是一个非常非常长的字符串

【问题讨论】:

  • 我们说的字符串有多长?高达几兆字节的内存缓冲将更容易且性能更高,除非您需要在生成结果时使用它们。
  • @DanielPryden 可能是“{owner} {permissions} {path}/{name}”乘以 4 年的小时数。我也在处理每个字符串,因为我只需要由\n 分隔的字符串的子字符串
  • *.com/questions/2715847/…proc.stdout.readline()
  • 如果您实际上正在获取文件系统信息,请不要为此使用子进程!使用os.listdir()(或者如果你需要子目录,可以使用os.walk())加上os.stat()来收集额外的信息。它不仅可以让您省去子进程和解析字符串的麻烦,而且总体上可能会更快。
  • @DanielPryden 不,它没有获取文件系统信息。 ll 只是一个很好的例子。我实际上正在运行 HDFS -ls 命令,但 ll 是一个很好的替代品,我认为更多人会理解并有类似的输出

标签: python subprocess


【解决方案1】:

如果您知道会出现什么错误消息,那么一个答案是将subprocess.STDOUT 传递给Popenstderr 参数,以便您的stderr 消息在stdout 流中:

proc = subprocess.Popen('ll'.split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

for i in proc.stdout:
   print(i)
   # check for error message strings and do something with them

或者,如果您不关心标准输出消息,那么只需迭代 stderr:

dnull = open(os.devnull, 'w')
proc = subprocess.Popen('ll'.split(), stdout=dnull, stderr=subprocess.PIPE)

for i in proc.stderr:
   print(i)
   # check for error message strings and do something with them

【讨论】: