【问题标题】:Python Popen stderr catch outputPython Popen stderr 捕获输出
【发布时间】:2015-02-16 22:15:25
【问题描述】:

我正在通过 Popen 运行命令并捕获 stderr 并使用它来更新其他地方的显示,这工作正常,每次 stderr 输出内容时都会更新,但我也在尝试将输出实时保存到日志文件.虽然这确实将输出写入文件,但似乎并不经常更新此文件。每次有东西要写时,有没有办法让输出写入文件? 代码如下:

self.process1 = Popen(command, startupinfo=startupinfo, stderr=subprocess.PIPE)
logFile = open(logFilePath, "a")
while True:
    line222 = self.process1.stderr.readline().decode('utf-8')
    logFile.write(line222)

【问题讨论】:

  • 我认为logFile.flush() 紧跟在logfFile.write() 之后会成功
  • 还有一个Popen的方法,我现在不记得了,你可以用它作为while循环的条件,它会逐行给你输出...需要检查文档
  • logFile.flush() 很好用,谢谢。

标签: python subprocess popen stderr


【解决方案1】:
for line in iter(self.process1.stderr.readline,b""):
    line222 = line.decode('utf-8')
    logFile.write(line222)
    logFile.flush()

【讨论】:

  • 代码已损坏。如果是 Python 2,那么 logFile.write(line.decode('utf-8')) 会中断,因为 logFile 写入的是 str 类型,而不是 unicode(第一个非 ascii 字符的异常)。如果是 Python 3,那么 iter(self.process1.stderr.readline,""): 永远不会停止,因为那里有 '' != b''
  • 如果您将文件传递给stderr(仅使用logfile.fileno()),则缓冲无关紧要。此外,OP 希望同时捕获 stderr(“每次 stderr 输出某些内容”以将其保存到文件中。
  • @J.F.Sebastian,我认为 OP 正在使用 python3 因为decode('utf-8') 我只是忘记了b。我不确定我是否理解关于 stderr 的观点,我在 OP 代码中的任何地方都看不到这一点。
  • 如果 OP 使用 Python 3,则使用 for line in self.process1.stderr: 代替 - 正如我在回答中提到的那样,这里不需要 iter()。要了解有关 stderr 的要点,look at the revision of your answer that my comment refers to.
  • universal_newlines 是使用 io.TextIOWrapper 实现的,它具有您可以查看的 Python 实现。一切都有缺点。甚至by fixing a bug; you could break somebody's workflow
【解决方案2】:

默认情况下,文件使用块缓冲,即在缓冲区溢出之前不会将任何内容写入磁盘。块大小通常为 4K 或 8K 字节。

在您的情况下,使文件行缓冲就足够了:

#!/usr/bin/env python
from __future__ import print_function
from subprocess import Popen, PIPE

p = Popen(command, startupinfo=startupinfo, 
          stderr=PIPE, bufsize=1,  # `1` means line-buffered (our end)
          universal_newlines=True) # convert to text, normalize newlines
with p.stderr, open(log_filename, "a", 1) as log_file: # `1` means line-buffered
    for line in iter(p.stderr.readline, ''):
        for file in [sys.stderr, log_file]:
            print(line, end='', file=file)
p.wait()

如果您使用的是 Python 3,则此处不需要iter()(此处已修复预读错误);你可以只使用for line in pipe:

我假设您已使用 utf-8 作为用户区域设置字符编码的占位符。

【讨论】:

    猜你喜欢
    • 2011-10-17
    • 2013-05-20
    • 2015-09-21
    • 1970-01-01
    • 2012-10-04
    • 1970-01-01
    • 2018-05-04
    • 2017-11-24
    • 1970-01-01
    相关资源
    最近更新 更多