tqdm in Jupyter Notebook stampa ripetutamente nuove barre di avanzamento


138

Sto usando tqdmper stampare i progressi in uno script che sto eseguendo su un quaderno Jupyter. Sto stampando tutti i messaggi sulla console tramite tqdm.write(). Tuttavia, questo mi dà ancora un output distorto in questo modo:

inserisci qui la descrizione dell'immagine

Cioè, ogni volta che deve essere stampata una nuova riga, sulla riga successiva viene stampata una nuova barra di avanzamento. Questo non accade quando eseguo lo script tramite terminale. Come posso risolvere questo?


In realtà, quando uso tqdm_notebook, posso anche fare normali prints, e non influisce sulla barra di avanzamento.
Tomasz Gandor,

in alternativa è quella di utilizzare questo progressbar stackoverflow.com/questions/3160699/python-progress-bar/...
eusoubrasileiro

Risposte:


216

Prova a utilizzare tqdm.notebook.tqdminvece di tqdm, come indicato qui .

Questo potrebbe essere semplice come cambiare l'importazione in:

from tqdm.notebook import tqdm

In bocca al lupo!

EDIT: dopo il test, sembra che funzioni tqdmdavvero bene in 'modalità testo' nel notebook Jupyter. È difficile da dire perché non hai fornito un esempio minimo , ma sembra che il tuo problema sia causato da un'istruzione di stampa in ogni iterazione. L'istruzione print sta superando un numero (~ 0,89) tra ogni aggiornamento della barra di stato, il che sta rovinando l'output. Prova a rimuovere la dichiarazione di stampa.


2
Non ho usato una print()dichiarazione, ho usato tqdm.write(). Tuttavia, tqdm_notebookdà buoni risultati. Grazie
:)

Sai se supporta Python 3.6? Non ho avuto fortuna con questo
Jon

1
Che errore stai ricevendo? Funziona bene per me. Impossibile aiutarti con così poche informazioni ... Hai abilitato ipywidgets in jupyer ? Hai semplicemente tqdm, piuttosto che tqdm_notebook? Funziona bene con Python 3.6 e Jupyter 1.0.0.
oscarbranson,

tqdm_notebook di tqdm 4.19.4 funziona per me su Python 3.6, Jupyter notebook 5.0.0 e ipywidgets 7.0.3.
Matt Kleinsmith,

2
@ bugmenot123 Buona cattura, risolto.
Czyzby,

39

Questa è una risposta alternativa nel caso in cui tqdm_notebook non funzioni per te.

Dato il seguente esempio:

from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values)) as pbar:
    for i in values:
        pbar.write('processed: %d' %i)
        pbar.update(1)
        sleep(1)

L'output sarebbe simile a questo (i progressi sarebbero visualizzati in rosso):

  0%|          | 0/3 [00:00<?, ?it/s]
processed: 1
 67%|██████▋   | 2/3 [00:01<00:00,  1.99it/s]
processed: 2
100%|██████████| 3/3 [00:02<00:00,  1.53it/s]
processed: 3

Il problema è che l'output di stdout e stderr viene elaborato in modo asincrono e separatamente in termini di nuove righe.

Se dice che Jupyter riceve su stderr la prima riga e quindi l'output "elaborato" su stdout. Quindi una volta ricevuto un output su stderr per aggiornare l'avanzamento, non tornerà indietro e aggiornerà la prima riga poiché aggiornerebbe solo l'ultima riga. Dovrà invece scrivere una nuova riga.

Soluzione 1, scrivere su stdout

Una soluzione alternativa sarebbe invece l'output di entrambi su stdout:

import sys
from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
    for i in values:
        pbar.write('processed: %d' % (1 + i))
        pbar.update(1)
        sleep(1)

L'output cambierà in (non più rosso):

processed: 1   | 0/3 [00:00<?, ?it/s]
processed: 2   | 0/3 [00:00<?, ?it/s]
processed: 3   | 2/3 [00:01<00:00,  1.99it/s]
100%|██████████| 3/3 [00:02<00:00,  1.53it/s]

Qui possiamo vedere che Jupyter non sembra cancellare fino alla fine della linea. Potremmo aggiungere un'altra soluzione alternativa aggiungendo spazi. Ad esempio:

import sys
from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
    for i in values:
        pbar.write('processed: %d%s' % (1 + i, ' ' * 50))
        pbar.update(1)
        sleep(1)

Che ci dà:

processed: 1                                                  
processed: 2                                                  
processed: 3                                                  
100%|██████████| 3/3 [00:02<00:00,  1.53it/s]

Soluzione 2, impostare invece la descrizione

In generale potrebbe essere più semplice non avere due uscite ma aggiornare invece la descrizione, ad esempio:

import sys
from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
    for i in values:
        pbar.set_description('processed: %d' % (1 + i))
        pbar.update(1)
        sleep(1)

Con l'output (descrizione aggiornata durante l'elaborazione):

processed: 3: 100%|██████████| 3/3 [00:02<00:00,  1.53it/s]

Conclusione

Per lo più puoi farlo funzionare bene con tqdm semplice. Ma se tqdm_notebook funziona per te, basta usarlo (ma probabilmente non avresti letto così lontano).


in alternativa è quella di utilizzare questo progressbar stackoverflow.com/a/34482761/1207193
eusoubrasileiro

Questa è di gran lunga la risposta migliore.
Rafay,

18

La maggior parte delle risposte è obsoleta ora. Meglio se importate correttamente tqdm .

from tqdm import tqdm_notebook as tqdm

inserisci qui la descrizione dell'immagine


7
È cambiato di nuovo:TqdmDeprecationWarning: This function will be removed in tqdm==5.0.0 Please use tqdm.notebook.tqdm instead of tqdm.tqdm_notebook
stason

10

Se gli altri suggerimenti qui non funzionano e, proprio come me, stai utilizzando l' pandasintegrazione progress_apply, puoi lasciarlo tqdmgestire:

from tqdm.autonotebook import tqdm
tqdm.pandas()

df.progress_apply(row_function, axis=1)

Il punto principale qui sta nel tqdm.autonotebookmodulo. Come indicato nelle loro istruzioni per l'uso nei Notebook IPython , questo fa tqdmscegliere tra i formati della barra di avanzamento utilizzati nei notebook Jupyter e nelle console Jupyter - per un motivo ancora privo di ulteriori indagini da parte mia, il formato specifico scelto da tqdm.autonotebookfunziona senza intoppi pandas, mentre tutti gli altri no per, in progress_applyparticolare.


9

Per completare la risposta di oscarbranson: è possibile selezionare automaticamente le versioni per console o notebook della barra di avanzamento a seconda di dove viene eseguita:

from tqdm.autonotebook import tqdm

Maggiori informazioni possono essere trovate qui


8

Nessuna delle precedenti funzioni per me. Trovo che correre per seguire questo problema dopo l'errore (cancella solo tutte le istanze delle barre di avanzamento in background):

from tqdm import tqdm

# blah blah your code errored

tqdm._instances.clear()

1
Grazie! Tuttavia genera ed errore se non esistono istanze. Voglio ancora usarlo con script e IDE di idrogeno. Ecco il mio codice try: # Avoids problem on notebooks / Hydrogen IDE tqdm.tqdm._instances.clear() except Exception: pass
Jacques Peeters,

Sì, genererà un'eccezione se non esiste alcuna istanza. C'è un problema con il tuo tentativo tranne l'approccio?
James Owers,

1

Per tutti coloro che si trovano su Windows e non sono in grado di risolvere il problema delle barre di duplicazione con nessuna delle soluzioni menzionate qui. Ho dovuto installare il coloramapacchetto come indicato nei problemi noti di tqdm che lo hanno risolto.

pip install colorama

Provalo con questo esempio:

from tqdm import tqdm
from time import sleep

for _ in tqdm(range(5), "All", ncols = 80, position = 0):
    for _ in tqdm(range(100), "Sub", ncols = 80, position = 1, leave = False):
        sleep(0.01)

Che produrrà qualcosa di simile:

All:  60%|████████████████████████                | 3/5 [00:03<00:02,  1.02s/it]
Sub:  50%|██████████████████▌                  | 50/100 [00:00<00:00, 97.88it/s]

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.