【问题标题】:Last unbuffered line can't be read无法读取最后一个未缓冲的行
【发布时间】:2014-11-13 10:58:23
【问题描述】:

我正在尝试从“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()

我已禁用子进程调用的输出缓冲以及 Python 进程的二进制输出(使用 -u 参数)。但我只得到第一行而不是第二行的进展。有人知道我如何做到这一点吗?

【问题讨论】:

标签: python-3.x subprocess pty


【解决方案1】:

如果apt-get 的标准输出被重定向到管道,例如,

$ apt-get download firefox | cat

然后它不报告进度(最后一行,例如,2% [1 firefox 646 kB/34.9 MB 2%]在输出中)。 stdout=subprocess.PIPE 自然创建了一个管道;因此apt-get 不会打印您的下载进度。

如果您既想捕获apt-get 输出,又想在屏幕上实时查看最后一行(进度报告),那么您可以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 模块:

#!/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 suggestedapt-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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-02
    • 2021-07-30
    • 2019-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-06
    相关资源
    最近更新 更多