tqdm
происходит от арабского слова taqaddum (تقدّم), которое может означать «прогресс», и является аббревиатурой испанской фразы «Я так сильно тебя люблю» ( te quiero demasiado ).
Мгновенно заставьте ваши циклы отображать умный индикатор прогресса — просто оберните любую итерацию с помощью tqdm(iterable)
, и все готово!
from tqdm import tqdm
for i in tqdm ( range ( 10000 )):
...
76%|████████████████████████ | 7568/10000 [00:33<00:10, 229.00it/s]
trange(N)
также можно использовать как удобный ярлык для tqdm(range(N))
.
Его также можно выполнить как модуль с трубами:
$ seq 9999999 | tqdm --bytes | wc -l
75.2MB [00:00, 217MB/s]
9999999
$ tar -zcf - docs/ | tqdm --bytes --total ` du -sb docs/ | cut -f1 `
> backup.tgz
32% | ██████████▍ | 8.89G/27.9G [00: 42< 01:31, 223MB/s]
Накладные расходы невелики — около 60 нс на итерацию (80 нс с tqdm.gui
), и они проходят модульное тестирование на предмет снижения производительности. Для сравнения, хорошо зарекомендовавший себя ProgressBar имеет накладные расходы 800 нс/итер.
В дополнение к низким накладным расходам tqdm
использует интеллектуальные алгоритмы для прогнозирования оставшегося времени и пропуска ненужных итераций, что в большинстве случаев допускает незначительные накладные расходы.
tqdm
работает на любой платформе (Linux, Windows, Mac, FreeBSD, NetBSD, Solaris/SunOS), на любой консоли или в графическом интерфейсе, а также совместим с ноутбуками IPython/Jupyter.
tqdm
не требует никаких зависимостей (даже curses
!), только Python и среда, поддерживающая символы carriage return r
и line feed n
.
Оглавление
contrib
asyncio
logging
pip install tqdm
Извлеките и установите предварительную ветку devel
:
pip install " git+https://github.com/tqdm/tqdm.git@devel#egg=tqdm "
conda install -c conda-forge tqdm
На выбор есть 3 канала:
snap install tqdm # implies --stable, i.e. latest tagged release
snap install tqdm --candidate # master branch
snap install tqdm --edge # devel branch
Обратите внимание, что двоичные файлы snap
предназначены исключительно для использования через CLI (не поддерживают import
) и автоматически настраивают завершение табуляции bash
.
docker pull tqdm/tqdm
docker run -i --rm tqdm/tqdm --help
Существуют и другие (неофициальные) места, откуда можно загрузить tqdm
, особенно для использования через CLI:
Список всех изменений доступен либо на GitHub’s Releases:, либо на вики, либо на веб-сайте.
tqdm
очень универсален и может использоваться разными способами. Три основных из них приведены ниже.
Оберните tqdm()
вокруг любой итерации:
from tqdm import tqdm
from time import sleep
text = ""
for char in tqdm ([ "a" , "b" , "c" , "d" ]):
sleep ( 0.25 )
text = text + char
trange(i)
— это специальный оптимизированный экземпляр tqdm(range(i))
:
from tqdm import trange
for i in trange ( 100 ):
sleep ( 0.01 )
Создание экземпляра вне цикла позволяет вручную управлять tqdm()
:
pbar = tqdm ([ "a" , "b" , "c" , "d" ])
for char in pbar :
sleep ( 0.25 )
pbar . set_description ( "Processing %s" % char )
Ручное управление обновлениями tqdm()
с помощью оператора with
:
with tqdm ( total = 100 ) as pbar :
for i in range ( 10 ):
sleep ( 0.1 )
pbar . update ( 10 )
Если указана необязательная переменная total
(или итерируемая с помощью len()
), отображается прогнозная статистика.
with
также является необязательным (вы можете просто присвоить tqdm()
переменной, но в этом случае не забудьте del
или close()
в конце:
pbar = tqdm ( total = 100 )
for i in range ( 10 ):
sleep ( 0.1 )
pbar . update ( 10 )
pbar . close ()
Возможно, самое замечательное использование tqdm
— это скрипт или командная строка. Простая вставка tqdm
(или python -m tqdm
) между каналами будет проходить через весь stdin
на stdout
при печати прогресса на stderr
.
В приведенном ниже примере демонстрируется подсчет количества строк во всех файлах Python в текущем каталоге с включенной информацией о времени.
$ time find . -name ' *.py ' -type f -exec cat { } ; | wc -l
857365
real 0m3.458s
user 0m0.274s
sys 0m3.325s
$ time find . -name ' *.py ' -type f -exec cat { } ; | tqdm | wc -l
857366it [00:03, 246471.31it/s]
857365
real 0m3.585s
user 0m0.862s
sys 0m3.358s
Обратите внимание, что также можно указать обычные аргументы для tqdm
.
$ find . -name ' *.py ' -type f -exec cat { } ; |
tqdm --unit loc --unit_scale --total 857366 >> /dev/null
100% | █████████████████████████████████ | 857K/857K [00: 04< 00:00, 246Kloc/s]
Резервное копирование большого каталога?
$ tar -zcf - docs/ | tqdm --bytes --total ` du -sb docs/ | cut -f1 `
> backup.tgz
44% | ██████████████▊ | 153M/352M [00: 14< 00:18, 11.0MB/s]
Это можно еще украсить:
$ BYTES= $( du -sb docs/ | cut -f1 )
$ tar -cf - docs/
| tqdm --bytes --total " $BYTES " --desc Processing | gzip
| tqdm --bytes --total " $BYTES " --desc Compressed --position 1
> ~ /backup.tgz
Processing: 100% | ██████████████████████ | 352M/352M [00: 14< 00:00, 30.2MB/s]
Compressed: 42% | █████████▎ | 148M/352M [00: 14< 00:19, 10.9MB/s]
Или сделать это на уровне файла с помощью 7-zip:
$ 7z a -bd -r backup.7z docs/ | grep Compressing
| tqdm --total $( find docs/ -type f | wc -l ) --unit files
| grep -v Compressing
100% | ██████████████████████████▉ | 15327/15327 [01: 00< 00:00, 712.96files/s]
Существующие программы CLI, уже выводящие базовую информацию о ходе выполнения, получат выгоду от флагов --update
и --update_to
tqdm
:
$ seq 3 0.1 5 | tqdm --total 5 --update_to --null
100% | ████████████████████████████████████ | 5.0/5 [00: 00< 00:00, 9673.21it/s]
$ seq 10 | tqdm --update --null # 1 + 2 + ... + 10 = 55 iterations
55it [00:00, 90006.52it/s]
Наиболее распространенные проблемы связаны с чрезмерным выводом в несколько строк вместо аккуратного однострочного индикатора выполнения.
CR
, r
).r
должным образом (cloudwatch, K8s), могут извлечь выгоду из export TQDM_POSITION=-1
.colorama
Python, чтобы вложенные столбцы оставались в пределах соответствующих строк.ascii
.tqdm
нет.tqdm(enumerate(...))
на enumerate(tqdm(...))
или tqdm(enumerate(x), total=len(x), ...)
. То же самое относится и к numpy.ndenumerate
.tqdm(zip(a, b))
на zip(tqdm(a), b)
или даже zip(tqdm(a), tqdm(b))
.itertools
.tqdm.contrib
.docker-compose run
вместо docker-compose up
и tty: true
.export TQDM_MININTERVAL=5
, чтобы избежать спама в журналах. Эта логика переопределения обрабатывается декоратором tqdm.utils.envwrap
(полезно независимо от tqdm
).Если вы столкнетесь с какими-либо другими трудностями, просмотрите и сохраните файлы .
(С 19 мая 2016 г.)
class tqdm ():
"""
Decorate an iterable object, returning an iterator which acts exactly
like the original iterable, but prints a dynamically updating
progressbar every time a value is requested.
"""
@ envwrap ( "TQDM_" ) # override defaults via env vars
def __init__ ( self , iterable = None , desc = None , total = None , leave = True ,
file = None , ncols = None , mininterval = 0.1 ,
maxinterval = 10.0 , miniters = None , ascii = None , disable = False ,
unit = 'it' , unit_scale = False , dynamic_ncols = False ,
smoothing = 0.3 , bar_format = None , initial = 0 , position = None ,
postfix = None , unit_divisor = 1000 , write_bytes = False ,
lock_args = None , nrows = None , colour = None , delay = 0 ):
Итерируемый для украшения индикатором выполнения. Оставьте пустым, чтобы управлять обновлениями вручную.
Префикс для индикатора прогресса.
Число ожидаемых итераций. Если не указано, по возможности используется len(iterable). Если float("inf") или в крайнем случае, отображается только базовая статистика прогресса (без расчетного времени прибытия и индикатора прогресса). Если gui
имеет значение True и этот параметр требует последующего обновления, укажите начальное произвольное большое положительное число, например 9e9.
Если [по умолчанию: True], сохраняет все следы индикатора выполнения после завершения итерации. Если None
, выход будет только в том случае, если position
равна 0
.
io.TextIOWrapper
или io.StringIO
, необязательно. Указывает, где выводить сообщения о ходе выполнения (по умолчанию: sys.stderr). Использует методы file.write(str)
и file.flush()
. Информацию о кодировании см. в write_bytes
.
Ширина всего выходного сообщения. Если указано, динамически изменяет размер индикатора выполнения, чтобы оставаться в пределах этой границы. Если не указано, пытается использовать ширину среды. Альтернативой является ширина 10 метров и отсутствие ограничений для счетчика и статистики. Если 0, счетчик не будет печататься (только статистика).
Минимальный интервал обновления отображения прогресса [по умолчанию: 0,1] секунд.
Максимальный интервал обновления отображения прогресса [по умолчанию: 10] секунд. Автоматически настраивает miniters
в соответствии с mininterval
после длительной задержки обновления дисплея. Работает только в том случае, если включены dynamic_miniters
или поток мониторинга.
Минимальный интервал обновления отображения прогресса, в итерациях. Если 0 и dynamic_miniters
, автоматически настраивается на равный mininterval
(более эффективное использование процессора, хорошо для узких циклов). Если > 0, отображение указанного количества итераций будет пропущено. Измените это и mininterval
чтобы получить очень эффективные циклы. Если ваш прогресс нестабильен как с быстрыми, так и с медленными итерациями (сеть, пропуск элементов и т. д.), вам следует установить miniters=1.
Если значение не указано или имеет значение False, для заполнения счетчика используйте Юникод (сглаженные блоки). Альтернативой является использование символов ASCII «123456789#».
Отключить ли всю оболочку индикатора выполнения [по умолчанию: False]. Если установлено значение «Нет», отключите режим без телетайпа.
Строка, которая будет использоваться для определения единицы измерения каждой итерации [по умолчанию: it].
Если установлено значение 1 или True, количество итераций будет уменьшено/масштабировано автоматически и будет добавлен префикс метрики, соответствующий стандарту Международной системы единиц (кило, мега и т. д.) [по умолчанию: False]. Если любое другое ненулевое число, будет масштабироваться total
и n
.
Если установлено, постоянно изменяет ncols
и nrows
в зависимости от среды (позволяя изменять размеры окна) [по умолчанию: False].
Экспоненциальный коэффициент сглаживания скользящего среднего для оценок скорости (игнорируется в режиме графического интерфейса). Диапазон значений от 0 (средняя скорость) до 1 (текущая/мгновенная скорость) [по умолчанию: 0,3].
Укажите пользовательское форматирование строки такта. Может повлиять на производительность. [по умолчанию: '{l_bar}{bar}{r_bar}'], где l_bar='{desc}: {percentage:3.0f}%|' и r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, ' '{rate_fmt}{postfix}]' Возможные переменные: l_bar, bar, r_bar, n, n_fmt, total, total_fmt, процент, elapsed, elapsed_s, ncols , nrows, desc, unit, скорость,rate_fmt,rate_noinv, rate_noinv_fmt,rate_inv,rate_inv_fmt, постфикс, unit_divisor, остаток, rest_s, эта. Обратите внимание, что завершающий знак ":" автоматически удаляется после {desc}, если последний пуст.
Начальное значение счетчика. Полезно при перезапуске индикатора выполнения [по умолчанию: 0]. При использовании float рассмотрите возможность указания {n:.3f}
или аналогичного в bar_format
или указания unit_scale
.
Укажите смещение линии для печати этой полосы (начиная с 0). Автоматически, если не указано. Полезно для одновременного управления несколькими стержнями (например, из потоков).
*
, необязательно Укажите дополнительную статистику, которая будет отображаться в конце панели. Вызывает set_postfix(**postfix)
если возможно (dict).
[по умолчанию: 1000], игнорируется, если unit_scale
не имеет значения True.
Записывать ли байты. Если (по умолчанию: False) будет записан Юникод.
Передается для refresh
для промежуточного вывода (инициализация, итерация и обновление).
Высота экрана. Если указано, скрывает вложенные столбцы за пределами этой границы. Если не указано, пытается использовать высоту среды. Резервный вариант — 20.
Цвет полосы (например, «зеленый», «#00ff00»).
Не отображать, пока не истечет [по умолчанию: 0] секунд.
delim
.delim
и по умолчанию для unit_scale
иметь значение True, unit_divisor
— 1024, а unit
— «B».stdin
передается как на stderr
, так и на stdout
.update()
. Обратите внимание, что это медленно (~ 2e5 и/с), поскольку каждый ввод должен быть декодирован как число.self.n
. Обратите внимание, что это медленно (~ 2e5 и/с), поскольку каждый ввод должен быть декодирован как число. class tqdm ():
def update ( self , n = 1 ):
"""
Manually update the progress bar, useful for streams
such as reading files.
E.g.:
>>> t = tqdm(total=filesize) # Initialise
>>> for current_buffer in stream:
... ...
... t.update(len(current_buffer))
>>> t.close()
The last line is highly recommended, but possibly not necessary if
``t.update()`` will be called in such a way that ``filesize`` will be
exactly reached and printed.
Parameters
----------
n : int or float, optional
Increment to add to the internal counter of iterations
[default: 1]. If using float, consider specifying ``{n:.3f}``
or similar in ``bar_format``, or specifying ``unit_scale``.
Returns
-------
out : bool or None
True if a ``display()`` was triggered.
"""
def close ( self ):
"""Cleanup and (if leave=False) close the progressbar."""
def clear ( self , nomove = False ):
"""Clear current bar display."""
def refresh ( self ):
"""
Force refresh the display of this bar.
Parameters
----------
nolock : bool, optional
If ``True``, does not lock.
If [default: ``False``]: calls ``acquire()`` on internal lock.
lock_args : tuple, optional
Passed to internal lock's ``acquire()``.
If specified, will only ``display()`` if ``acquire()`` returns ``True``.
"""
def unpause ( self ):
"""Restart tqdm timer from last print time."""
def reset ( self , total = None ):
"""
Resets to 0 iterations for repeated use.
Consider combining with ``leave=True``.
Parameters
----------
total : int or float, optional. Total to use for the new bar.
"""
def set_description ( self , desc = None , refresh = True ):
"""
Set/modify description of the progress bar.
Parameters
----------
desc : str, optional
refresh : bool, optional
Forces refresh [default: True].
"""
def set_postfix ( self , ordered_dict = None , refresh = True , ** tqdm_kwargs ):
"""
Set/modify postfix (additional stats)
with automatic formatting based on datatype.
Parameters
----------
ordered_dict : dict or OrderedDict, optional
refresh : bool, optional
Forces refresh [default: True].
kwargs : dict, optional
"""
@ classmethod
def write ( cls , s , file = sys . stdout , end = " n " ):
"""Print a message via tqdm (without overlap with bars)."""
@ property
def format_dict ( self ):
"""Public API for read-only member access."""
def display ( self , msg = None , pos = None ):
"""
Use ``self.sp`` to display ``msg`` in the specified ``pos``.
Consider overloading this function when inheriting to use e.g.:
``self.some_frontend(**self.format_dict)`` instead of ``self.sp``.
Parameters
----------
msg : str, optional. What to display (default: ``repr(self)``).
pos : int, optional. Position to ``moveto``
(default: ``abs(self.pos)``).
"""
@ classmethod
@ contextmanager
def wrapattr ( cls , stream , method , total = None , bytes = True , ** tqdm_kwargs ):
"""
stream : file-like object.
method : str, "read" or "write". The result of ``read()`` and
the first argument of ``write()`` should have a ``len()``.
>>> with tqdm.wrapattr(file_obj, "read", total=file_obj.size) as fobj:
... while True:
... chunk = fobj.read(chunk_size)
... if not chunk:
... break
"""
@ classmethod
def pandas ( cls , * targs , ** tqdm_kwargs ):
"""Registers the current `tqdm` class with `pandas`."""
def trange ( * args , ** tqdm_kwargs ):
"""Shortcut for `tqdm(range(*args), **tqdm_kwargs)`."""
def tqdm . contrib . tenumerate ( iterable , start = 0 , total = None ,
tqdm_class = tqdm . auto . tqdm , ** tqdm_kwargs ):
"""Equivalent of `numpy.ndenumerate` or builtin `enumerate`."""
def tqdm . contrib . tzip ( iter1 , * iter2plus , ** tqdm_kwargs ):
"""Equivalent of builtin `zip`."""
def tqdm . contrib . tmap ( function , * sequences , ** tqdm_kwargs ):
"""Equivalent of builtin `map`."""
class tqdm . notebook . tqdm ( tqdm . tqdm ):
"""IPython/Jupyter Notebook widget."""
class tqdm . auto . tqdm ( tqdm . tqdm ):
"""Automatically chooses beween `tqdm.notebook` and `tqdm.tqdm`."""
class tqdm . asyncio . tqdm ( tqdm . tqdm ):
"""Asynchronous version."""
@ classmethod
def as_completed ( cls , fs , * , loop = None , timeout = None , total = None ,
** tqdm_kwargs ):
"""Wrapper for `asyncio.as_completed`."""
class tqdm . gui . tqdm ( tqdm . tqdm ):
"""Matplotlib GUI version."""
class tqdm . tk . tqdm ( tqdm . tqdm ):
"""Tkinter GUI version."""
class tqdm . rich . tqdm ( tqdm . tqdm ):
"""`rich.progress` version."""
class tqdm . keras . TqdmCallback ( keras . callbacks . Callback ):
"""Keras callback for epoch and batch progress."""
class tqdm . dask . TqdmCallback ( dask . callbacks . Callback ):
"""Dask callback for task progress."""
contrib
Пакет tqdm.contrib
также содержит экспериментальные модули:
tqdm.contrib.itertools
: тонкие оболочки вокруг itertools
tqdm.contrib.concurrent
: тонкие оболочки вокруг concurrent.futures
tqdm.contrib.slack
: сообщения для ботов Slack.tqdm.contrib.discord
: Публикации для ботов Discord.tqdm.contrib.telegram
: Публикации для ботов Telegram.tqdm.contrib.bells
: автоматически включает все дополнительные функции.auto
, pandas
, slack
, discord
, telegram
help()
; Пользовательскую информацию можно отображать и обновлять динамически на панелях tqdm
с помощью аргументов desc
и postfix
:
from tqdm import tqdm , trange
from random import random , randint
from time import sleep
with trange ( 10 ) as t :
for i in t :
# Description will be displayed on the left
t . set_description ( 'GEN %i' % i )
# Postfix will be displayed on the right,
# formatted automatically based on argument's datatype
t . set_postfix ( loss = random (), gen = randint ( 1 , 999 ), str = 'h' ,
lst = [ 1 , 2 ])
sleep ( 0.1 )
with tqdm ( total = 10 , bar_format = "{postfix[0]} {postfix[1][value]:>8.2g}" ,
postfix = [ "Batch" , { "value" : 0 }]) as t :
for i in range ( 10 ):
sleep ( 0.1 )
t . postfix [ 1 ][ "value" ] = i / 2
t . update ()
Что следует помнить при использовании {postfix[...]}
в строке bar_format
:
postfix
также необходимо передать в качестве начального аргумента в совместимом формате иpostfix
будет автоматически преобразован в строку, если это объект типа dict
. Чтобы предотвратить такое поведение, вставьте в словарь дополнительный элемент, ключ которого не является строкой. Дополнительные параметры bar_format
также могут быть определены путем переопределения format_dict
, а сама панель может быть изменена с помощью ascii
:
from tqdm import tqdm
class TqdmExtraFormat ( tqdm ):
"""Provides a `total_time` format parameter"""
@ property
def format_dict ( self ):
d = super (). format_dict
total_time = d [ "elapsed" ] * ( d [ "total" ] or 0 ) / max ( d [ "n" ], 1 )
d . update ( total_time = self . format_interval ( total_time ) + " in total" )
return d
for i in TqdmExtraFormat (
range (