我正在使用pty
来读取非阻塞此过程的标准输出:
import os
import pty
import subprocess
master, slave = pty.openpty()
p = subprocess.Popen(cmd, stdout = slave)
stdout = os.fdopen(master)
while True:
if p.poll() != None:
break
print stdout.readline()
stdout.close()
除了while-loop
偶尔阻止外,一切正常。这是因为行print stdout.readline()
正在等待从stdout
读取内容。但如果程序已经终止,我的小脚本就会永远挂起。
我的问题是:有没有办法窥视stdout
对象并检查是否有可供读取的数据?如果不是这种情况,它应该继续通过while-loop
,它将发现该进程实际上已经终止并打破了循环。
答案 0 :(得分:10)
是的,请使用select module's poll:
import select
q = select.poll()
q.register(stdout,select.POLLIN)
并且在使用中:
l = q.poll(0)
if not l:
pass # no input
else:
pass # there is some input
答案 1 :(得分:2)
select.poll()答案非常简洁,但在Windows上无效。以下解决方案是另一种选择。它不允许你偷看stdout,但提供了readline()的非阻塞替代方案,并且基于this answer:
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=(dcmpid,)) #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()
已提出其他非阻塞读取解决方案here,但对我不起作用: