2013-02-15 17 views
6

Ho visto diverse soluzioni per una barra di avanzamento in Python, ma le semplici soluzioni stdout non funzionano per il mio progetto. Ho più classi e uso il modulo "logging" per inviare informazioni a STDOUT. Ho una funzione di cui voglio mostrare una barra di avanzamento su una riga, svuotando il buffer ogni volta.Barra di avanzamento Python TRAMITE il modulo di registrazione

Esempio del semplice progresso:

for i in range(100): 
    time.sleep(1) 
    sys.stdout.write("\r%d%%" %i) 
    sys.stdout.flush() 

Quando tento di scrivere via STDOUT e quindi svuotare il buffer, o il buffer non è arrossato o il progresso non va da nessuna parte. Spero di evitare una sorta di processo di threading o complicato per renderlo possibile. Qualcuno ha un modo preferito per farlo accadere?

risposta

0

Se conosce la barra di avanzamento sta andando sempre essere scritta su STDOUT, si dovrebbe utilizzare print invece di un registratore. Vedere la documentazione in the Python logging tutorial documentation

+0

Il problema con l'utilizzo di "stampa" è che getta ogni valore su una nuova riga non rendendo l'output una barra di avanzamento. Si suppone che STDOUT svuoti il ​​buffer e scriva sulla linea esistente, ma questo non sembra funzionare quando lo si utilizza nel codice che sta registrando. Intendiamoci, non sto avvolgendo la sintassi del modulo di registrazione sul codice a barre di avanzamento. –

+1

Usando il codice esatto che hai postato sopra, vedo l'output che viene sostituito in posizione. Vedete ciascun numero su una nuova riga? – jknupp

1

È possibile utilizzare il tqdm progress bar con a custom handler through logging as described here:

import logging 
import time 
import colorlog 
from tqdm import tqdm 

class TqdmHandler(logging.StreamHandler): 
    def __init__(self): 
     logging.StreamHandler.__init__(self) 

    def emit(self, record): 
     msg = self.format(record) 
     tqdm.write(msg) 

if __name__ == "__main__": 
    for x in tqdm(range(100)): 
     logger = colorlog.getLogger("MYAPP") 
     logger.setLevel(logging.DEBUG) 
     handler = TqdmHandler() 
     handler.setFormatter(colorlog.ColoredFormatter(
      '%(log_color)s%(name)s | %(asctime)s | %(levelname)s | %(message)s', 
      datefmt='%Y-%d-%d %H:%M:%S', 
      log_colors={ 
       'DEBUG': 'cyan', 
       'INFO': 'white', 
       'SUCCESS:': 'green', 
       'WARNING': 'yellow', 
       'ERROR': 'red', 
       'CRITICAL': 'red,bg_white'},)) 

     logger.addHandler(handler) 
     logger.debug("Inside subtask: "+str(x)) 
     time.sleep(.5) 
+0

Non funziona per me. Penso, puoi provare questo: https://gist.github.com/w495/80f6a7351a10d5b6cecb5dad6c8cd8d6 –

3

ho risolto in questo modo:

import logging 
import time 
from tqdm import tqdm 
import io 

class TqdmToLogger(io.StringIO): 
    """ 
     Output stream for TQDM which will output to logger module instead of 
     the StdOut. 
    """ 
    logger = None 
    level = None 
    buf = '' 
    def __init__(self,logger,level=None): 
     super(TqdmToLogger, self).__init__() 
     self.logger = logger 
     self.level = level or logging.INFO 
    def write(self,buf): 
     self.buf = buf.strip('\r\n\t ') 
    def flush(self): 
     self.logger.log(self.level, self.buf) 

if __name__ == "__main__": 
    logging.basicConfig(format='%(asctime)s [%(levelname)-8s] %(message)s') 
    logger = logging.getLogger() 
    logger.setLevel(logging.DEBUG) 

    tqdm_out = TqdmToLogger(logger,level=logging.INFO) 
    for x in tqdm(range(100),file=tqdm_out,mininterval=30,): 
     time.sleep(.5) 

uscita

2016-12-19 15:35:06 [INFO ] 16%|#####9        | 768/4928 [07:04<40:50, 1.70it/s] 
2016-12-19 15:36:07 [INFO ] 18%|######6        | 865/4928 [08:04<40:34, 1.67it/s] 
+0

Solo curioso da dove viene il numero alla fine della barra di avanzamento '##### 9', e come può ci sbarazziamo di esso? – Sam

+0

Penso che sia il 16,9% e il 18,6% (il punto decimale). – ddofborg

2

non riuscivo a trovare un buona soluzione per questo, quindi ho scritto enlighten progress bar per gestirlo. Fondamentalmente cambia l'area di scorrimento del terminale in modo che la registrazione venga eseguita al di sopra delle barre di avanzamento piuttosto che dover ridisegnare le barre di avanzamento ogni volta che si desidera scrivere su STDOUT. Questo ti permette di scrivere sul terminale quanto vuoi senza dover modificare logging, print, ecc.

Dovrebbe funzionare sulla maggior parte dei terminali non Windows. Il supporto di Windows potrebbe venire in futuro, ma nessuno lo ha ancora chiesto.

import logging 
import time 
import enlighten 

# Setup logging 
logging.basicConfig(level=logging.INFO) 
logger = logging.getLogger() 

# Setup progress bar 
manager = enlighten.get_manager() 
pbar = manager.counter(total=100, desc='Ticks', unit='ticks') 

for i in range(1, 101): 
    logger.info("Processing step %s" % i) 
    time.sleep(.2) 
    pbar.update() 
+0

Ho appena scoperto questo modulo, esattamente quello di cui avevo bisogno! Grazie per questo. –

Problemi correlati