tqdm в Jupyter Notebook несколько раз печатает новые индикаторы выполнения


138

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

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

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


На самом деле, когда я использую tqdm_notebook, я могу даже делать обычные printс, и это не влияет на индикатор выполнения.
Томаш Гандор

альтернативой является использование этого progressbar stackoverflow.com/questions/3160699/python-progress-bar/…
eusoubrasileiro

Ответы:


217

Попробуйте использовать tqdm.notebook.tqdmвместо tqdm, как описано здесь .

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

from tqdm.notebook import tqdm

Удачи!

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


2
Я не использовал print()заявление, я использовал tqdm.write(). Однако tqdm_notebookдает хорошие результаты. Спасибо
Рохан Саксена

Вы знаете, поддерживает ли он Python 3.6? Мне не повезло с этим
Джон

1
Какую ошибку вы получаете? Он отлично работает для меня. Невозможно помочь с такой маленькой информацией ... Вы включили ipywidgets в jupyer ? Вы просто tqdm, а не tqdm_notebook? Это хорошо работает с Python 3.6 и Jupyter 1.0.0.
oscarbranson

tqdm_notebook из tqdm 4.19.4 работает для меня на Python 3.6, Jupyter notebook 5.0.0 и ipywidgets 7.0.3.
Мэтт

2
@ bugmenot123 Хороший улов, исправлено.
Czyzby

39

Это альтернативный ответ на случай, когда 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 работает для вас, просто используйте его (но тогда вы, вероятно, не прочитали бы это далеко).


альтернативой является использование этого progressbar stackoverflow.com/a/34482761/1207193
eusoubrasileiro

Это лучший ответ на сегодняшний день.
Рафаи

18

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

from tqdm import tqdm_notebook as tqdm

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


7
Снова изменилось:TqdmDeprecationWarning: This function will be removed in tqdm==5.0.0 Please use tqdm.notebook.tqdm instead of tqdm.tqdm_notebook
stason

10

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

from tqdm.autonotebook import tqdm
tqdm.pandas()

df.progress_apply(row_function, axis=1)

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


9

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

from tqdm.autonotebook import tqdm

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


8

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

from tqdm import tqdm

# blah blah your code errored

tqdm._instances.clear()

1
Спасибо! Однако он выдает и ошибку, если не существует экземпляров. Еще хочу использовать его со скриптами и Hydrogen IDE. Вот мой код. try: # Avoids problem on notebooks / Hydrogen IDE tqdm.tqdm._instances.clear() except Exception: pass
Жак Питерс

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

1

Для всех, кто работает в 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]

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.