La riga dell’ultimo unbuffered non può essere letta

Sto cercando di leggere l’ultima riga da un comando come ‘apt-get download firefox’. Normalmente l’output sarà simile

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 l’ultima riga in continuo aggiornamento (non sta scrivendo una nuova riga fino a quando non raggiunge il 100%). Il mio objective è ora di leggere i progressi in tempo reale. Ecco il mio codice di esempio corrente:

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

Ho disabilitato il buffering dell’output per la chiamata subprocess e anche per l’output binario per il processo Python (con l’argomento -u). Ma sto solo ricevendo la prima riga ma non i progressi della seconda linea. Qualcuno sa come posso ottenere questo?

    Se lo stdout di apt-get viene reindirizzato a una pipe, ad es.

     $ apt-get download firefox | cat 

    quindi non riporta il progresso (l’ultima riga, ad es. 2% [1 firefox 646 kB/34.9 MB 2%] non sarà presente nell’output). stdout=subprocess.PIPE crea naturalmente una pipe; quindi apt-get non stampa i progressi del download nel tuo caso.

    Se si desidera sia acquisire l’output apt-get sia visualizzarlo sullo schermo in tempo reale con l’ultima riga (report di avanzamento) presente, è ansible utilizzare il modulo pexpect per ingannare il processo figlio nel pensare che venga eseguito in un terminale :

     import sys import pexpect # $ pip install pexpect output, exitstatus = pexpect.runu('apt-get download firefox', logfile=sys.stdout, withexitstatus=1) 

    Puoi fare lo stesso usando solo il modulo 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 su Python Il tracker dei --quiet opzione --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)