【问题标题】:Processing messages from a child process thorough stderr and stdout with Python使用 Python 通过 stderr 和 stdout 处理来自子进程的消息
【发布时间】:2011-06-15 21:20:45
【问题描述】:

我的 python 代码生成子进程,并打印出 stdout 和 stderr 消息。 我需要以不同的方式打印它们。

我有以下代码来生成子进程并从中获取标准输出结果。

cmd = ["vsmake.exe", "-f"]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
for line in iter(p.stdout.readline, ''):
    print line,
    sys.stdout.flush()
    pass
p.wait()

如何修改代码以检查子进程是否也通过 stderr 打印出消息?

添加

只要子进程打印出一些东西,我就需要打印出 stderr 和 stdout。而且是跨平台实现,所以应该可以在Mac/Linux/PC上运行。

【问题讨论】:

  • 您想同时在 stdout 和 stderr 上实时打印消息吗?如果是,您可能需要在 Windows 上使用线程(因为既没有 select() 也没有非阻塞 I/O)。
  • 我编辑了我的答案,以便在这两个管道中的任何一个中打印一行后立即打印 stderr 和 stdout。

标签: python stdout stderr spawn child-process


【解决方案1】:

独立于平台执行此操作的最简单方法是使用线程(不幸的是)。下面是一些示例代码:

def redirect_to_stdout(stream):
    for line in stream:
        sys.stdout.write(line)
        sys.stdout.flush()

cmd = ["vsmake.exe", "-f"]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stderr_thread = threading.Thread(target=redirect_to_stdout, args=(p.stderr,))
stderr_thread.start()
redirect_to_stdout(p.stdout)
p.wait()
stderr_thread.join()

【讨论】:

  • -1:s/运行/开始/。使用stderr=subprocess.STDOUT 重定向stdout
  • @J.F. Sebastian:感谢您指出start()/run() 的困惑,现在更正。使用 stderr=subprocess.STDOUT 不可能满足 OP 的“以不同方式打印 [stdout 和 stderr]”的要求。如果你可以那样做,你根本不需要线程。
  • 没错,您的解决方案不会以不同的方式打印 stdout、stderr;在这种情况下它不需要线程。
【解决方案2】:
p = Popen(cmd, bufsize=1024,
stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
p.stdin.close()
print p.stdout.read() #This will print the standard output from the spawned process
print p.stderr.read() #This is what you need, error output <-----

所以基本上错误输出被重定向到stderr管道。

如果您需要更多实时信息。我的意思是,一旦生成的进程向stdout orstderr 打印了一些东西,就会打印行,然后你可以执行以下操作:

def print_pipe(type_pipe,pipe):
    for line in iter(pipe.readline, ''):
         print "[%s] %s"%(type_pipe,line),

p = Popen(cmd, bufsize=1024,
stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)

t1 = Thread(target=print_pipe, args=("stdout",p.stdout,))
t1.start()
t2 = Thread(target=print_pipe, args=("stderr",p.stderr,))
t2.start()

#optionally you can join the threads to wait till p is done. This is avoidable but it 
# really depends on the application.
t1.join()
t2.join()

在这种情况下,每次将一行写入stdoutstderr 时都会打印两个线程。参数type_pipe 只是在打印行时区分它们是来自stderr 还是stdout

【讨论】:

  • 我最喜欢的(对于小输出)是:stdin,stdout = p.communicate()。一口气搞定一切!然后用 stdin,stdout 做你想做的事。
  • 不错的一个! (+1) 我不知道那个。
  • 鉴于问题中的示例代码,我怀疑 OP 想要实时打印输出。但在他告诉我们之前,我们无法确定这一点。
  • 你应该修复你的print 语句——% 操作符会像现在这样失败。还要记住line 以“\n”结尾,你不想打印两次。
  • 1.如果输出足够大,第一个示例可以阻塞。 stackoverflow.com/questions/163542/… 2. 除非必须,否则不要使用shell=True。列表cmd 的语义不同。 3. 您可以在print 语句的末尾添加, 而不是line.replace()。 3.应该有p.wait()t1.join(),t2.join()某处。
猜你喜欢
  • 2015-04-12
  • 1970-01-01
  • 1970-01-01
  • 2011-07-07
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
  • 2020-06-23
  • 1970-01-01
相关资源
最近更新 更多