【发布时间】:2016-10-15 19:48:02
【问题描述】:
我正在为测试套件中的进程编写某种看门狗。我需要确定测试是否挂起。
我可以简单地使用subprocess.Popen(...) 启动该过程,然后使用Popen.wait(timeout=to) 或Popen.poll() 并保留我自己的计时器。然而,测试在执行时间上差别很大,这使得不可能有一个对所有测试都合理的“超时”值。
我发现确定测试是否挂起的一个好方法是在进程最后一次输出任何内容时设置一个“超时”。为此,我考虑使用
process = subprocess.Popen(args='<program>', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ...)
和Popen.communicate(),以确定stdout 和/或stderr 何时不是None。问题是Popen.communicate(),没有“超时”只会等到进程终止,而“超时”会引发TimeoutExpired 异常,我无法确定是否读取了任何内容。 TimeoutExpired.output 是空的,顺便说一句。
我在文档中找不到任何允许手动执行“读取”的内容。此外,该进程通常有很多输出,因此以stdout=<open_file_descriptor> 开头将是有益的,因为我不会担心溢出管道缓冲区。
更新/解决方案:
Popen.stdout 和 Popen.stderr 返回一个“可读流对象”,可用于手动轮询/选择和读取。我最终使用了 select 'Polling Objects',它使用了 poll() 系统调用,如下所示:
import os
import select
import subprocess
p = subprocess.Popen(args="<program>", shell=True, universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
poll_obj = select.poll()
poll_obj.register(p.stdout, select.POLLIN)
poll_obj.register(p.stderr, select.POLLIN)
while p.poll() is None:
events = True
while events:
events = poll_obj.poll(10)
for fd, event in events:
if event & select.POLLIN:
print("STDOUT: " if fd == p.stdout.fileno() else "STDERR: ")
print(os.read(fd, 1024).decode())
# else some other error (see 'Polling Objects')
【问题讨论】:
标签: python linux subprocess