tqdm в Jupyter Notebook багаторазово друкує нові смужки прогресу


138

Я використовую tqdmдля друку прогрес у сценарії, який я виконую в зошиті Юпітера. Я друкую всі повідомлення на консоль через tqdm.write(). Однак це все одно дає мені перекошений вихід таким чином:

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

Тобто, кожного разу, коли потрібно друкувати новий рядок, на наступному рядку друкується нова смужка прогресу. Це не відбувається, коли я запускаю скрипт через термінал. Як я можу це вирішити?


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

альтернативою є використання цього progressbar stackoverflow.com/questions/3160699/python-progress-bar / ...
eusoubrasileiro

Відповіді:


216

Спробуйте використовувати tqdm.notebook.tqdmзамість tqdm, як зазначено тут .

Це може бути просто, як змінити імпорт на:

from tqdm.notebook import tqdm

Удачі!

EDIT: Після тестування, здається, що tqdmнасправді це добре працює в «текстовому режимі» в ноутбуці Юпітера. Важко сказати, тому що ви не надали мінімального прикладу , але, схоже, ваша проблема викликана викладом друку в кожній ітерації. Оператор друку виводить число (~ 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, ноутбук Юпітер 5.0.0 та ipywidgets 7.0.3.
Метт Клейнсміт

2
@ bugmenot123 Хороший улов, виправлено.
Чізбі

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 обробляються асинхронно та окремо у вигляді нових рядків.

Якщо сказати, Юпітер отримує на stderr перший рядок, а потім "оброблений" вихід на stdout. Тоді як тільки він отримає вихід на stderr для оновлення прогресу, він не повернеться та не оновлює перший рядок, оскільки оновить лише останній рядок. Натомість йому доведеться написати новий рядок.

Обхід 1, написання до stdout

Одним із варіантів вирішення проблеми буде виведення обох на 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)

Вихід зміниться на (не більше червоного):

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]

Тут ми можемо побачити, що Юпітер, здається, не очищається до кінця рядка. Для цього ми могли б додати ще одне вирішення, додавши пробіли. Як от:

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
стасон

10

Якщо інші поради тут не спрацьовують, і, як і я, ви використовуєте pandasінтеграцію progress_apply, ви можете дозволити tqdmїй впоратися:

from tqdm.autonotebook import tqdm
tqdm.pandas()

df.progress_apply(row_function, axis=1)

Основний момент тут полягає в tqdm.autonotebookмодулі. Як зазначено в їхніх інструкціях щодо використання в ноутбуках IPython , це дозволяє tqdmвибирати між форматами панелі прогресу, використовуваними в ноутбуках Юпітера та консолях Юпітера - з моєї сторони, як і раніше не вистачає подальших розслідувань, конкретний формат, вибраний програмою, 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
Дякую! Однак він кидає і помиляє, якщо жодних екземплярів не існує. Ще хочете використовувати його зі сценаріями та Водневим IDE. Ось мій код. try: # Avoids problem on notebooks / Hydrogen IDE tqdm.tqdm._instances.clear() except Exception: pass
Жак Пітерс

Так, це викине виняток, якщо жодного примірника не існує. Чи є проблема з вашим спробу, крім підходу?
Джеймс Оверс

1

Для всіх, хто перебуває у вікні та не зміг вирішити проблему дублювання барів жодним із згаданих тут рішень. Мені довелося встановити 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.