最后一个无缓冲行不能被读取
我正在尝试从“apt-get download firefox”这样的命令中读取最后一行。 通常情况下,输出会是这样的
Get:1 http://archive.ubuntu.com/ubuntu/ utopic/main firefox amd64 32.0+build1-0ubuntu2 [34.9 MB] 2% [1 firefox 646 kB/34.9 MB 2%]
最后一行不断更新(直到达到100%才写出换行符)。 我的目标是实时读取进度。 这是我目前的示例代码:
#!/usr/bin/python3 -u # coding=utf-8 import subprocess, sys pipe = subprocess.Popen(['apt-get', 'download', 'firefox'], 0, stderr = subprocess.PIPE, stdout = subprocess.PIPE) while True: content = pipe.stdout.read(1).decode() if content == '': break sys.stdout.write(content) sys.stdout.flush() pipe.wait()
我已经禁用了subprocess调用的输出缓冲,也禁用了Python进程的二进制输出(使用-u参数)。 但是我只得到第一行,而不是第二行的进度。 有人知道我怎么能做到这一点?
如果apt-get
stdout被redirect到一个pipe道,例如,
$ apt-get download firefox | cat
那么它不会报告进度(最后一行例如2% [1 firefox 646 kB/34.9 MB 2%]
将不在输出中)。 stdout=subprocess.PIPE
自然会创build一个pipe道; 因此apt-get
不打印您的情况下的下载进度。
如果你想同时捕获apt-get
输出和在屏幕上实时显示最后一行(进度报告),那么你可以使用pexpect
模块来欺骗subprocess,使其认为它运行在terminal上 :
import sys import pexpect # $ pip install pexpect output, exitstatus = pexpect.runu('apt-get download firefox', logfile=sys.stdout, withexitstatus=1)
你可以只使用stdlib pty
模块来做同样的事情:
#!/usr/bin/env python3 import os import pty output = [] def read(fd): data = os.read(fd, 1024) output.append(data) return data status = pty.spawn(['apt-get', 'download', 'firefox'], read)
关于Python的@eryksun问题跟踪器build议使用 apt-get
的--quiet
选项:
#!/usr/bin/env python3 import shlex from io import TextIOWrapper from subprocess import Popen, PIPE output = [] with Popen(shlex.split("apt-get --quiet=0 download firefox"), stdout=PIPE, bufsize=1) as p: # recognize '\r' as newline but don't convert it to '\n' for line in TextIOWrapper(p.stdout, newline=''): print(line, end='', flush=True) # print to terminal output.append(line) # save for later print(p.returncode)