tqdm en Jupyter Notebook imprime nuevas barras de progreso repetidamente

138

Estoy usando tqdmpara imprimir el progreso en un script que estoy ejecutando en un cuaderno Jupyter. Estoy imprimiendo todos los mensajes a la consola a través de tqdm.write(). Sin embargo, esto todavía me da una salida sesgada como esta:

ingrese la descripción de la imagen aquí

Es decir, cada vez que se debe imprimir una nueva línea, se imprime una nueva barra de progreso en la siguiente línea. Esto no sucede cuando ejecuto el script a través de la terminal. ¿Como puedo resolver esto?

Rohan Saxena
fuente
En realidad, cuando lo uso tqdm_notebook, incluso puedo hacer prints normales , y no afecta la barra de progreso.
Tomasz Gandor
una alternativa es usar este progressbar stackoverflow.com/questions/3160699/python-progress-bar/…
eusoubrasileiro

Respuestas:

216

Intente usar en tqdm.notebook.tqdmlugar de tqdm, como se describe aquí .

Esto podría ser tan simple como cambiar su importación a:

from tqdm.notebook import tqdm

¡Buena suerte!

EDITAR: después de probar, parece que tqdmrealmente funciona bien en 'modo de texto' en el cuaderno Jupyter. Es difícil saberlo porque no ha proporcionado un ejemplo mínimo , pero parece que su problema es causado por una declaración de impresión en cada iteración. La declaración de impresión está superando un número (~ 0.89) entre cada actualización de la barra de estado, lo que está desordenando la salida. Intente eliminar la declaración de impresión.

oscarbranson
fuente
2
No he usado una print()declaración, solía tqdm.write(). Sin embargo, tqdm_notebookda buenos resultados. Gracias
:)
¿Sabes si es compatible con Python 3.6? No he tenido suerte con esto
Jon
1
¿Qué error estás recibiendo? Funciona bien para mí. Imposible ayudar con tan poca información ... ¿Ha habilitado ipywidgets en jupyer ? ¿Simplemente tqdm, en lugar de tqdm_notebook? Esto funciona bien con Python 3.6 y Jupyter 1.0.0.
oscarbranson
tqdm_notebook de tqdm 4.19.4 me funciona en Python 3.6, Jupyter notebook 5.0.0 e ipywidgets 7.0.3.
Matt Kleinsmith
2
@ bugmenot123 Buena captura, corregida.
Czyzby
39

Esta es una respuesta alternativa para el caso donde tqdm_notebook no funciona para usted.

Dado el siguiente ejemplo:

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)

El resultado se vería así (el progreso se mostraría en rojo):

  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

El problema es que la salida a stdout y stderr se procesan de forma asíncrona y por separado en términos de nuevas líneas.

Si digamos, Jupyter recibe en stderr la primera línea y luego la salida "procesada" en stdout. Luego, una vez que recibe una salida en stderr para actualizar el progreso, no volvería y actualizaría la primera línea, ya que solo actualizaría la última línea. En su lugar, tendrá que escribir una nueva línea.

Solución 1, escribir en stdout

Una solución alternativa sería generar ambos en stdout en su lugar:

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)

La salida cambiará a (no más rojo):

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]

Aquí podemos ver que Jupyter no parece despejarse hasta el final de la línea. Podríamos agregar otra solución para eso agregando espacios. Como:

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)

Lo que nos da:

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

Solución 2, establezca la descripción en su lugar

En general, podría ser más sencillo no tener dos salidas, sino actualizar la descripción, por ejemplo:

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 la salida (descripción actualizada mientras se está procesando):

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

Conclusión

En su mayoría, puede hacer que funcione bien con tqdm simple. Pero si tqdm_notebook funciona para usted, solo use eso (pero probablemente no leería tan lejos).

de1
fuente
una alternativa es usar este progressbar stackoverflow.com/a/34482761/1207193
eusoubrasileiro
Esta es la mejor respuesta con diferencia.
Rafay
18

La mayoría de las respuestas están desactualizadas ahora. Mejor si importa tqdm correctamente.

from tqdm import tqdm_notebook as tqdm

ingrese la descripción de la imagen aquí

Shritam Kumar Mund
fuente
77
Cambió nuevamente:TqdmDeprecationWarning: This function will be removed in tqdm==5.0.0 Please use tqdm.notebook.tqdm instead of tqdm.tqdm_notebook
stason
10

Si los otros consejos aquí no funcionan y, al igual que yo, está utilizando la pandasintegración progress_apply, puede dejar de tqdmmanejarlo:

from tqdm.autonotebook import tqdm
tqdm.pandas()

df.progress_apply(row_function, axis=1)

El punto principal aquí radica en el tqdm.autonotebookmódulo. Como se indica en sus instrucciones de uso en las computadoras portátiles IPython , esto hace que tqdmelegir entre los formatos de barra de progreso utilizados en las computadoras portátiles Jupyter y las consolas Jupyter, por una razón que aún carece de más investigaciones de mi parte, el formato específico elegido por tqdm.autonotebookfunciona sin problemas pandas, mientras que todos los demás no lo hicieron. 't, por progress_applyespecíficamente.

Julio Cezar Silva
fuente
9

Para completar la respuesta de oscarbranson: es posible elegir automáticamente versiones de consola o portátil de la barra de progreso dependiendo de dónde se ejecuta:

from tqdm.autonotebook import tqdm

Más información se puede encontrar aquí

mjarosie
fuente
8

Nada de lo anterior funciona para mí. Me parece que ejecutar lo siguiente soluciona este problema después del error (solo borra todas las instancias de barras de progreso en segundo plano):

from tqdm import tqdm

# blah blah your code errored

tqdm._instances.clear()
James Owers
fuente
1
¡Gracias! Sin embargo, arroja un error si no existe ninguna instancia. Todavía quiero usarlo con scripts e IDE de hidrógeno. Aquí está mi código. try: # Avoids problem on notebooks / Hydrogen IDE tqdm.tqdm._instances.clear() except Exception: pass
Jacques Peeters
Sí, lanzará una excepción si no existe una instancia. ¿Hay algún problema con su intento, excepto el enfoque?
James Owers
1

Para todos los que están en Windows y no pudieron resolver el problema de las barras duplicadas con ninguna de las soluciones mencionadas aquí. Tuve que instalar el coloramapaquete como se indica en los problemas conocidos de tqdm que lo arreglaron.

pip install colorama

Pruébalo con este ejemplo:

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)

Lo que producirá algo como:

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

Utilice tqdm_notebook

from tqdm import 
tqdm_notebook as tqdm

x=[1,2,3,4,5]

for i in tqdm(len(x)):

    print(x[i])
Kranthi Kumar Valaboju
fuente