Python 从子流程获取进度消息
我想开始一个需要几分钟才能完成的程序。在此期间,我想阅读程序的进度消息(打印在标准输出上)。问题是我找不到一种方法在运行期间读取它的输出 我找到的唯一读取程序输出的函数是Python 从子流程获取进度消息,python,subprocess,Python,Subprocess,我想开始一个需要几分钟才能完成的程序。在此期间,我想阅读程序的进度消息(打印在标准输出上)。问题是我找不到一种方法在运行期间读取它的输出 我找到的唯一读取程序输出的函数是Popen.communicate(),但此方法会等到进程完成。因此,不可能以一种特殊的格式化方式获取进度并使其对用户可见 有没有可能用另一种方法 当我用脚本运行带有subprocess.popen的进程时,我会在屏幕上看到程序的输出。有可能把它藏起来吗?(Ubuntu 10.10,普通终端)您可以对子进程的状态进行轮询,并保持
Popen.communicate()
,但此方法会等到进程完成。因此,不可能以一种特殊的格式化方式获取进度并使其对用户可见
有没有可能用另一种方法
当我用脚本运行带有
subprocess.popen
的进程时,我会在屏幕上看到程序的输出。有可能把它藏起来吗?(Ubuntu 10.10,普通终端)您可以对子进程的状态进行轮询,并保持输出行
p = subprocess.Popen('ls;sleep 10', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
rc = p.poll()
while rc != 0:
while True:
line = p.stdout.readline()
if not line:
break
print line
rc = p.poll()
assert rc == 0
最简单的方法是使用关键字参数调用Popen
stdout=subprocess.PIPE
p = subprocess.Popen(["ls"], stdout=subprocess.PIPE)
while True:
line = p.stdout.readline()
if not line:
break
print line
要了解这一点,这里有两个示例脚本。将它们放在同一个目录中并运行
python superprint.py
printandwait.py:
import time
import sys
print 10
sys.stdout.flush()
time.sleep(10)
print 20
sys.stdout.flush()
superprint.py:
import subprocess
import sys
p = subprocess.Popen(["python printandwait.py"], shell=True, stdout=subprocess.PIPE)
while True:
print "Looping"
line = p.stdout.readline()
if not line:
break
print line.strip()
sys.stdout.flush()
这当然是可能的:我的包就是这样做的,在一个子进程下生成
gpg
(Gnu隐私保护)。在一般情况下,需要为子流程stdout和stderr指定subprocess.PIPE
;然后创建两个单独的线程,将子进程stdout和stderr读取到您喜欢的任何位置
在python gnupg
的情况下,当gpg
进程运行时(不等待它完成),会读取来自gpg的状态消息并对其执行操作
基本上,伪代码是
process = subprocess.Popen(..., stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stderr = process.stderr
rr = threading.Thread(target=response_reader_func, args=(process.stderr,))
rr.setDaemon(True)
rr.start()
dr = threading.Thread(target=data_reader_func, args=(process.stdout,))
dr.setDaemon(True)
dr.start()
dr.join()
rr.join()
process.wait()
reader函数通常是一个封闭类的方法,它根据所读取的内容做正确的事情(在您的情况下,以某种方式更新进度信息)。如果在您打破while循环后一些数据到达,该怎么办?@Neo:他的示例在EOF中断,这意味着在此之后无法再到达更多数据。但是,为了回答您的问题:如果您不继续读取标准输出管道,缓冲区可能会填满,子进程将阻止尝试写入标准输出。它将在p.stdout中等待您稍后使用。但是,readline调用将被阻止,直到新输入到达或管道关闭。添加了一些示例脚本。您可以对iter中的行(p.stdout.readline,b'')使用
:打印行,
,而不是while
-循环。