无法读取最后未缓冲的行 [英] Last unbuffered line can't be read
问题描述
我正在尝试从apt-get download firefox"之类的命令中读取最后一行.通常输出会像
I'm trying to read the last line from a command like 'apt-get download firefox'. Normally the output will be like
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% 才写入换行符).我现在的目标是实时阅读进度.这是我当前的示例代码:
with the last line continuously updating (it is not writing a newline until it reaches 100%). My goal is now to read the progress in realtime. Here is my current example code:
#!/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()
我已经禁用了子进程调用的输出缓冲以及 Python 进程的二进制输出(使用 -u 参数).但我只得到第一行,而不是第二行的进度.有人知道我如何实现这一目标吗?
I have disabled the output buffering for the subprocess call and also for binary output for the Python process (with the -u argument). But I'm only getting the first line but not the progress of the second line. Does somebody know how I can achieve this?
推荐答案
如果 apt-get
的 stdout 被重定向到管道,例如,
If stdout of apt-get
is redirected to a pipe e.g.,
$ apt-get download firefox | cat
然后它不报告进度(最后一行例如 2% [1 firefox 646 kB/34.9 MB 2%]
将不出现在输出中).stdout=subprocess.PIPE
自然会创建一个管道;因此 apt-get
不会在您的情况下打印下载进度.
then it doesn't report progress (the last line e.g., 2% [1 firefox 646 kB/34.9 MB 2%]
will not be in the output). stdout=subprocess.PIPE
naturally creates a pipe; therefore apt-get
doesn't print the download progress in your case.
如果您想要捕获 apt-get
输出并在屏幕上实时查看它并显示最后一行(进度报告),那么您可以 使用pexpect
模块诱使子进程认为它在终端中运行:
If you want both to capture apt-get
output and to see it on the screen in real-time with the last line (progress report) present then you could use pexpect
module to trick the child process into thinking that it runs in a terminal:
import sys
import pexpect # $ pip install pexpect
output, exitstatus = pexpect.runu('apt-get download firefox',
logfile=sys.stdout,
withexitstatus=1)
你可以只使用 stdlib pty
模块来做同样的事情:
You could do the same using only stdlib pty
module:
#!/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)
@eryksun on Python Issue tracker 建议 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)
这篇关于无法读取最后未缓冲的行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!