select.poll ()答案非常简洁,但不适用于 Windows。以下解决方案是一种替代方案。它不允许您查看标准输出,但提供了 readline() 的非阻塞替代方案,并且基于此答案:
from subprocess import Popen, PIPE
from threading import Thread
def process_output(myprocess): #output-consuming thread
nextline = None
buf = ''
while True:
#--- extract line using read(1)
out = myprocess.stdout.read(1)
if out == '' and myprocess.poll() != None: break
if out != '':
buf += out
if out == '\n':
nextline = buf
buf = ''
if not nextline: continue
line = nextline
nextline = None
#--- do whatever you want with line here
print 'Line is:', line
myprocess.stdout.close()
myprocess = Popen('myprogram.exe', stdout=PIPE) #output-producing process
p1 = Thread(target=process_output, args=(myprocess,)) #output-consuming thread
p1.daemon = True
p1.start()
#--- do whatever here and then kill process and thread if needed
if myprocess.poll() == None: #kill process; will automatically stop thread
myprocess.kill()
myprocess.wait()
if p1 and p1.is_alive(): #wait for thread to finish
p1.join()
这里提出了其他非阻塞读取的解决方案,但对我不起作用:
- 需要 readline 的解决方案(包括基于队列的解决方案)总是阻塞。很难(不可能?)杀死执行 readline 的线程。它仅在创建它的进程完成时被杀死,而不是在输出生成进程被杀死时。
- 正如 anonnn 所指出的,将低级 fcntl 与高级 readline 调用混合可能无法正常工作。
- 使用 select.poll() 很简洁,但根据 python 文档在 Windows 上不起作用。
- 对于此任务,使用第三方库似乎有点过分,并且会增加额外的依赖项。