TQDM в ноутбуке Jupyter

Я использую tqdm чтобы распечатать прогресс в сценарии, я бегу в блокноте Jupyter. Я печатаю все сообщения на консоль через tqdm.write(), Тем не менее, это все еще дает мне искаженный вывод примерно так:

введите описание изображения здесь

То есть каждый раз, когда должна быть напечатана новая строка, новая строка прогресса печатается на следующей строке. Этого не происходит, когда я запускаю скрипт через терминал. Как я могу решить это?

13 ответов

Решение

Попробуйте использовать tqdm_notebook вместо tqdm, как изложено здесь. На данном этапе это экспериментально, но в большинстве случаев работает довольно хорошо.

Это может быть так же просто, как изменить ваш импорт на:

from tqdm import tqdm_notebook as tqdm

Удачи!

РЕДАКТИРОВАТЬ: после тестирования, кажется, что tqdm на самом деле отлично работает в "текстовом режиме" в ноутбуке Jupyter. Трудно сказать, потому что вы не предоставили минимальный пример, но похоже, что ваша проблема вызвана оператором print в каждой итерации. Оператор печати выдает число (~0,89) между каждым обновлением строки состояния, что портит вывод. Попробуйте удалить оператор печати.

Это альтернативный ответ для случая, когда tqdm_notebook не работает для вас.

Учитывая следующий пример:

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)

Вывод будет выглядеть примерно так (прогресс будет отображаться красным):

  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

Проблема в том, что выходные данные в stdout и stderr обрабатываются асинхронно и раздельно в терминах новых строк.

Если, скажем, Jupyter получает на stderr первую строку, а затем "обработанный" вывод на stdout. Затем, как только он получит вывод на stderr для обновления хода выполнения, он не вернется назад и не обновит первую строку, поскольку обновит только последнюю строку. Вместо этого он должен будет написать новую строку.

Обходной путь 1, запись в стандартный вывод

Один из обходных путей - вместо этого вывести оба на стандартный вывод:

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)

Выход изменится на (не более красный):

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]

Здесь мы видим, что Jupyter, кажется, не очищается до конца строки. Мы могли бы добавить другой обходной путь для этого, добавив пробелы. Такие как:

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)

Что дает нам:

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

Обходной путь 2, установите описание вместо

В целом, может быть более простым не иметь два выхода, а вместо этого обновить описание, например:

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)

С выводом (описание обновляется во время его обработки):

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

Заключение

В основном вы можете заставить его работать нормально с простым tqdm. Но если tqdm_notebook работает для вас, просто используйте это (но тогда вы, вероятно, не прочитали бы это далеко).

Большинство ответов сейчас устарели. Лучше, если вы правильно импортируете tqdm.

from tqdm import tqdm_notebook as tqdm

введите описание изображения здесь

Чтобы завершить ответ Оскарбрансона: можно автоматически выбрать версию индикатора выполнения для консоли или ноутбука в зависимости от того, откуда он запускается:

from tqdm.autonotebook import tqdm

Более подробную информацию можно найти здесь

У меня ничего из вышеперечисленного не работает. Я обнаружил, что запуск следующих видов этой проблемы после ошибки (он просто очищает все экземпляры индикаторов выполнения в фоновом режиме):

from tqdm import tqdm

# blah blah your code errored

tqdm._instances.clear()

Если другие советы здесь не работают и - так же, как я - вы используете pandas интеграция через progress_applyможете tqdm справиться:

from tqdm.auto import tqdm
tqdm.pandas()

df.progress_apply(row_function, axis=1)

Главное здесь заключается в tqdm.auto модуль. Как указано в их инструкции по использованию в ноутбуках IPython, это делает tqdm выбирать между форматами индикатора выполнения, используемыми в ноутбуках Jupyter и консолях Jupyter - по причине, которая все еще не требует дальнейших исследований с моей стороны, в конкретном формате, выбранном tqdm.auto работает плавно в pandasв то время как все остальные не progress_apply в частности.

Для всех, кто работает в Windows и не может решить проблему дублирования полос с помощью любого из упомянутых здесь решений. Мне пришлось установитьcoloramaпакет, как указано в известных проблемах tqdm, которые его исправили.

pip install colorama

Попробуйте это на следующем примере:

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)

Что даст что-то вроде:

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

С использованием Python 3.9.2а также tqdm==4.62.3:

      from tqdm.notebook import tqdm

for item in tqdm(list_of_items):
    do_something(item)

tqdmавтоматически загружает индикатор выполнения подгонки либо для обычного кода, либо для интерактивной среды через

      from tqdm.auto import tqdm

Используйте tqdm_notebook

from tqdm import 
tqdm_notebook as tqdm

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

for i in tqdm(len(x)):

    print(x[i])

Это работает как положено, если вы делаете следующее:

pbar = tqdm(range(10))
try:
    for i in pbar:
        sleep(1)
        if i==5:
            raise NotImplementedError()
finally:
    pbar.close()

или же

with tqdm(range(10)) as pbar:
    for i in pbar:
        sleep(1)
        if i==5:
            raise NotImplementedError()

В моем случае мне просто нужно было обновить ipywidgets, чтобы избавиться от лишней печати при использовании обычного from tqdm import tqdm.

Еще один пример индикатора выполнения с использованием tqdm

      from tqdm import tqdm

my_list = list(range(100))

with tqdm(total=len(my_list)) as pbar:
    for x in my_list:
        pbar.update(1)
Другие вопросы по тегам