[英]In python, How do I check the stdout from a subprocess.Popen object for anything to read?
在 python 中,如何检查 subprocess.Popen 对象的标准输出是否有任何要读取的内容? 我正在为一个有时连续运行数小时的工具编写一个包装器。 在子进程的标准输出上使用 .readline() 会严重降低脚本运行时间超过几分钟的速度。 如果有任何要阅读的内容,我需要一种更有效地检查标准输出的方法。 顺便说一下,这个特殊的工具一次只能写完整的行。 脚本是这样的:
#!/usr/bin/python -u
#thiswrap.py
import sys, time
from subprocess import *
chldp = Popen(sys.argv[1], bufsize=0, stdout=PIPE, close_fds=True)
chstdin,chstdout=chldp.stdin,chldp.stdout
startnoti=False
while not chldp.poll():
rrl=chstdout.readline() # <--- this is where the problem is
if rrl[-8:]=='REDACTED TEXT':
sys.stdout.write(rrl[:-1]+' \r')
if not startnoti: startnoti=True
else:
if startnoti: sys.stdout.write('\n')
sys.stdout.write(rrl)
if startnoti: # REDACTED
time.sleep(0.1)
time.sleep(0.1)
有任何想法吗?
您需要将文件描述符设置为非阻塞,您可以使用fcntl执行此操作:
import sys, time, fcntl, os
from subprocess import *
chldp = Popen(sys.argv[1], bufsize=0, stdout=PIPE, close_fds=True)
chstdin, chstdout = chldp.stdin, chldp.stdout
fl = fcntl.fcntl(chstdout, fcntl.F_GETFL)
fcntl.fcntl(chstdout, fcntl.F_SETFL, fl | os.O_NONBLOCK)
while chldp.poll() is not None:
try:
rrl = chstdout.readline()
except IOError:
time.sleep(0.1)
continue
# use rrl
当没有可用数据时, readline()
将IOError
。
请注意,由于chldp.poll()
在子childp.poll() is not None
完成时可能返回0
,因此您可能应该在while
使用childp.poll() is not None
而不是not childp.poll()
。
可悲的是,没有现成的方法来轮询条件“管道中有足够的数据与换行符,因此 readline() 将立即返回”。
如果您一次想要一行,并且不想阻塞,您可以:
通过类或生成器实现您自己的缓冲并通过它进行轮询,例如:
def linereader():
data = ""
while True:
if poll(f.fd):
data += f.read(100)
lines = data.split("\n")
data = lines[-1]
for line in lines[:-1]:
yield line
# use
for line in linereader():
if line:
print line
else:
time.sleep(...)
或者使用线程(留给读者作为练习,请注意,如果您从主线程以外的线程启动子进程,则旧版本的 python 错误)
第一条评论中提出的解决方案几乎是正确的。 您只需要将整数文件描述符作为第一个参数传递给fcntl.fcntl
,而不是 Python 文件对象。 取自另一个答案
这是要更改的代码:
chstdout = chldp.stdout
fd = chstdout.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.