Sto usando tqdm
in Python per visualizzare le barre di avanzamento della console nei nostri script. Tuttavia, devo chiamare le funzioni che i messaggi print
alla console e che non posso cambiare. In generale, la scrittura alla console durante la visualizzazione di barre di avanzamento nella console scombina il display in questo modo:Comando di reindirizzamento della stampa in script python tramite tqdm.write()
from time import sleep
from tqdm import tqdm
def blabla():
print "Foo blabla"
for k in tqdm(range(3)):
blabla()
sleep(.5)
Questo crea l'output:
0%| | 0/3 [00:00<?, ?it/s]Foo
blabla
33%|###########6 | 1/3 [00:00<00:01, 2.00it/s]Foo
blabla
67%|#######################3 | 2/3 [00:01<00:00, 2.00it/s]Foo
blabla
100%|###################################| 3/3 [00:01<00:00, 2.00it/s]
According to the documentation of tqdm
il metodo tqdm.write()
fornisce un mezzo per scrivere messaggi alla console senza interrompere i progressbar visualizzati. Così, l'uscita giusta è fornita da questo frammento:
from time import sleep
from tqdm import tqdm
def blabla():
tqdm.write("Foo blabla")
for k in tqdm(range(3)):
blabla()
sleep(.5)
E assomiglia a questo:
Foo blabla
Foo blabla
Foo blabla
100%|###################################| 3/3 [00:01<00:00, 1.99it/s]
D'altra parte, c'è questa solution which permits to silence those functions da molto elegantemente reindirizzando sys.stdout
nel vuoto. Questo funziona perfettamente per mettere a tacere le funzioni.
Dal momento che voglio per visualizzare i messaggi da queste funzioni comunque senza rompere le barre di avanzamento, ho cercato di unire le due soluzioni in un unico reindirizzando sys.stdout
a tqdm.write()
e, a sua volta, lasciando tqdm.write()
scrittura alla vecchiosys.stdout
. Il risultato è il frammento:
from time import sleep
import contextlib
import sys
from tqdm import tqdm
class DummyFile(object):
file = None
def __init__(self, file):
self.file = file
def write(self, x):
tqdm.write(x, file=self.file)
@contextlib.contextmanager
def nostdout():
save_stdout = sys.stdout
sys.stdout = DummyFile(save_stdout)
yield
sys.stdout = save_stdout
def blabla():
print "Foo blabla"
for k in tqdm(range(3)):
with nostdout():
blabla()
sleep(.5)
Tuttavia, questo crea effettivamente una potenza ancora più incasinato di prima:
0%| | 0/3 [00:00<?, ?it/s]Foo
blabla
33%|###########6 | 1/3 [00:00<00:01, 2.00it/s]Foo
blabla
67%|#######################3 | 2/3 [00:01<00:00, 2.00it/s]Foo
blabla
100%|###################################| 3/3 [00:01<00:00, 2.00it/s]
FYI: chiamando tqdm.write(..., end="")
all'interno DummyFile.write()
crea lo stesso risultato della prima uscita che è ancora incasinato.
Non riesco a capire perché questo non funzionerebbe, dal momento che tqdm.write()
deve gestire la cancellazione della barra di avanzamento prima di scrivere il messaggio e quindi riscrivere la barra di avanzamento.
Cosa mi manca?
Se 'blabla()' rilancio un errore, lo stdout standard non verrà mai ripristinato. – Conchylicultor