O tqdm no Jupyter Notebook imprime novas barras de progresso repetidamente

138

Estou usando tqdmpara imprimir o progresso de um script que estou executando em um notebook Jupyter. Estou imprimindo todas as mensagens no console via tqdm.write(). No entanto, isso ainda me dá uma saída assimétrica assim:

insira a descrição da imagem aqui

Ou seja, cada vez que uma nova linha precisa ser impressa, uma nova barra de progresso é impressa na próxima linha. Isso não acontece quando eu executo o script via terminal. Como posso resolver isso?

Rohan Saxena
fonte
Na verdade, quando eu uso tqdm_notebook, posso fazer prints normais , e isso não afeta a barra de progresso.
Tomasz Gandor
uma alternativa é usar este progressbar stackoverflow.com/questions/3160699/python-progress-bar/...
eusoubrasileiro

Respostas:

216

Tente usar em tqdm.notebook.tqdmvez de tqdm, conforme descrito aqui .

Isso pode ser tão simples quanto alterar sua importação para:

from tqdm.notebook import tqdm

Boa sorte!

EDIT: Após o teste, parece que tqdmrealmente funciona bem no 'modo de texto' no notebook Jupyter. É difícil dizer porque você não forneceu um exemplo mínimo , mas parece que seu problema é causado por uma declaração de impressão em cada iteração. A instrução de impressão está gerando um número (~ 0,89) entre cada atualização da barra de status, que está atrapalhando a saída. Tente remover a declaração de impressão.

oscarbranson
fonte
2
Eu não usei uma print()declaração, eu usei tqdm.write(). No entanto, tqdm_notebookdá bons resultados. Obrigado
:)
Você sabe se ele suporta Python 3.6? Eu não tive sorte com isso
Jon
1
que erro você está tendo? Isso funciona bem para mim. Impossível ajudar com tão pouca informação ... Você ativou os ipywidgets no jupyer ? Você simplesmente planeja tqdm, e não tqdm_notebook? Isso funciona bem com o Python 3.6 e o ​​Jupyter 1.0.0.
Oscarbranson #
O tqdm_notebook do tqdm 4.19.4 está funcionando para mim no Python 3.6, Jupyter notebook 5.0.0 e ipywidgets 7.0.3.
precisa
2
@ bugmenot123 Boa captura, corrigida.
Czyzby 15/01
39

Esta é uma resposta alternativa para o caso em que tqdm_notebook não funciona para você.

Dado o seguinte exemplo:

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)

A saída seria mais ou menos assim (o progresso seria exibido em vermelho):

  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

O problema é que a saída para stdout e stderr é processada de forma assíncrona e separada em termos de novas linhas.

Se, por exemplo, o Jupyter recebe no stderr a primeira linha e a saída "processada" no stdout. Então, uma vez que ele recebe uma saída no stderr para atualizar o progresso, ele não volta e atualiza a primeira linha, pois atualiza apenas a última linha. Em vez disso, terá que escrever uma nova linha.

Solução alternativa 1, gravando no stdout

Uma solução alternativa seria produzir ambos para 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)

A saída mudará para (não mais vermelho):

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]

Aqui podemos ver que Jupyter parece não estar limpo até o final da linha. Poderíamos adicionar outra solução alternativa para isso adicionando espaços. Tal 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)

O que nos dá:

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

Solução 2, defina a descrição em vez disso

Em geral, pode ser mais direto não ter duas saídas, mas atualizar a descrição, por exemplo:

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)

Com a saída (descrição atualizada durante o processamento):

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

Conclusão

Você pode fazê-lo funcionar bem com o tqdm comum. Mas se o tqdm_notebook funcionar para você, use-o (mas você provavelmente não leria até agora).

de1
fonte
uma alternativa é usar este progressbar stackoverflow.com/a/34482761/1207193
eusoubrasileiro
Esta é a melhor resposta de longe.
Rafay 03/12/19
18

A maioria das respostas está desatualizada agora. Melhor se você importar o tqdm corretamente.

from tqdm import tqdm_notebook as tqdm

insira a descrição da imagem aqui

Shritam Kumar Mund
fonte
7
Ele mudou novamente:TqdmDeprecationWarning: This function will be removed in tqdm==5.0.0 Please use tqdm.notebook.tqdm instead of tqdm.tqdm_notebook
stason
10

Se as outras dicas aqui não funcionarem e - assim como eu - você estiver usando a pandasintegração progress_apply, pode tqdmlidar com isso:

from tqdm.autonotebook import tqdm
tqdm.pandas()

df.progress_apply(row_function, axis=1)

O ponto principal aqui reside no tqdm.autonotebookmódulo. Conforme indicado em suas instruções para uso em notebooks IPython , isso faz a tqdmescolha entre os formatos de barra de progresso usados ​​nos notebooks Jupyter e nos consoles Jupyter - por um motivo ainda carente de mais investigações do meu lado, o formato específico escolhido por tqdm.autonotebookfuncionar sem problemas pandas, enquanto todos os outros não para, progress_applyespecificamente.

Julio Cezar Silva
fonte
9

Para concluir a resposta do oscarbranson: é possível escolher automaticamente versões de console ou notebook da barra de progresso, dependendo de onde está sendo executada:

from tqdm.autonotebook import tqdm

Mais informações podem ser encontradas aqui

mjarosie
fonte
8

Nenhuma das opções acima funciona para mim. Acho que executar o seguinte classifica esse problema após um erro (ele limpa todas as instâncias das barras de progresso em segundo plano):

from tqdm import tqdm

# blah blah your code errored

tqdm._instances.clear()
James Owers
fonte
1
Obrigado! No entanto, lança e erro se não houver instâncias. Ainda deseja usá-lo com scripts e o Hydrogen IDE. Aqui está o meu código. try: # Avoids problem on notebooks / Hydrogen IDE tqdm.tqdm._instances.clear() except Exception: pass
Jacques Peeters
Sim, ele lançará uma exceção se nenhuma instância existir. Existe algum problema com sua tentativa, exceto a abordagem?
James Owers 29/03
0

Para todos que estão no Windows e não conseguiram resolver o problema das barras duplicadas com qualquer uma das soluções mencionadas aqui. Eu tive que instalar o coloramapacote como indicado nos problemas conhecidos do tqdm que o corrigiam .

pip install colorama

Experimente com este exemplo:

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)

O que produzirá 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
fonte
0

Use 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
fonte