python 3.x - que - La última línea sin búfer no se puede leer
subprocess python 3 call (1)
Si stdout de
apt-get
se redirige a una tubería, por ejemplo,
$ apt-get download firefox | cat
entonces no informa el progreso (la última línea, por ejemplo,
2% [1 firefox 646 kB/34.9 MB 2%]
no
estará en la salida).
stdout=subprocess.PIPE
crea naturalmente una tubería;
por lo tanto,
apt-get
no imprime el progreso de descarga en su caso.
Si desea capturar la salida de
apt-get
y verla en la pantalla en tiempo real con la última línea (informe de progreso) presente, puede
usar el módulo
pexpect
para engañar al proceso secundario para que piense que se ejecuta en un terminal
:
import sys
import pexpect # $ pip install pexpect
output, exitstatus = pexpect.runu(''apt-get download firefox'',
logfile=sys.stdout,
withexitstatus=1)
Puede hacer lo mismo usando solo el módulo 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 en Python Issue tracker sugirió la
opción
--quiet
apt-get
:
#!/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)
Estoy tratando de leer la última línea de un comando como ''apt-get download firefox''. Normalmente la salida será como
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%]
con la última línea actualizando continuamente (no está escribiendo una nueva línea hasta que alcanza el 100%). Mi objetivo ahora es leer el progreso en tiempo real. Aquí está mi código de ejemplo actual:
#!/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()
He deshabilitado el búfer de salida para la llamada de subproceso y también para la salida binaria para el proceso de Python (con el argumento -u). Pero solo estoy obteniendo la primera línea, pero no el progreso de la segunda línea. ¿Alguien sabe cómo puedo lograr esto?