tqdm
deriva da palavra árabe taqaddum (تقدّم), que pode significar "progresso", e é uma abreviatura de "eu te amo tanto" em espanhol ( te quiero demasiado ).
Faça com que seus loops mostrem instantaneamente um medidor de progresso inteligente - basta agrupar qualquer iterável com tqdm(iterable)
e pronto!
from tqdm import tqdm
for i in tqdm ( range ( 10000 )):
...
76%|████████████████████████ | 7568/10000 [00:33<00:10, 229.00it/s]
trange(N)
também pode ser usado como um atalho conveniente para tqdm(range(N))
.
Também pode ser executado como um módulo com pipes:
$ 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]
A sobrecarga é baixa - cerca de 60ns por iteração (80ns com tqdm.gui
) e é testada em unidade contra regressão de desempenho. Em comparação, o bem estabelecido ProgressBar tem uma sobrecarga de 800ns/iter.
Além de sua baixa sobrecarga, tqdm
usa algoritmos inteligentes para prever o tempo restante e evitar exibições de iteração desnecessárias, o que permite uma sobrecarga insignificante na maioria dos casos.
tqdm
funciona em qualquer plataforma (Linux, Windows, Mac, FreeBSD, NetBSD, Solaris/SunOS), em qualquer console ou em uma GUI, e também é compatível com notebooks IPython/Jupyter.
tqdm
não requer nenhuma dependência (nem mesmo curses
!), apenas Python e um ambiente que suporte caracteres de controle carriage return r
e line feed n
.
Índice
contrib
asyncio
logging
pip install tqdm
Extraia e instale o branch devel
de pré-lançamento:
pip install " git+https://github.com/tqdm/tqdm.git@devel#egg=tqdm "
conda install -c conda-forge tqdm
Existem 3 canais para escolher:
snap install tqdm # implies --stable, i.e. latest tagged release
snap install tqdm --candidate # master branch
snap install tqdm --edge # devel branch
Observe que os binários snap
são puramente para uso CLI (não import
) e configuram automaticamente o preenchimento de tabulação bash
.
docker pull tqdm/tqdm
docker run -i --rm tqdm/tqdm --help
Existem outros locais (não oficiais) onde tqdm
pode ser baixado, especialmente para uso CLI:
A lista de todas as alterações está disponível nos lançamentos do GitHub:, no wiki ou no site.
tqdm
é muito versátil e pode ser usado de várias maneiras. Os três principais são apresentados a seguir.
Enrole tqdm()
em torno de qualquer iterável:
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)
é uma instância especial otimizada de tqdm(range(i))
:
from tqdm import trange
for i in trange ( 100 ):
sleep ( 0.01 )
A instanciação fora do loop permite o controle manual sobre tqdm()
:
pbar = tqdm ([ "a" , "b" , "c" , "d" ])
for char in pbar :
sleep ( 0.25 )
pbar . set_description ( "Processing %s" % char )
Controle manual de atualizações tqdm()
usando uma instrução with
:
with tqdm ( total = 100 ) as pbar :
for i in range ( 10 ):
sleep ( 0.1 )
pbar . update ( 10 )
Se a variável opcional total
(ou um iterável com len()
) for fornecida, as estatísticas preditivas serão exibidas.
with
também é opcional (você pode simplesmente atribuir tqdm()
a uma variável, mas neste caso não se esqueça de del
ou close()
no final:
pbar = tqdm ( total = 100 )
for i in range ( 10 ):
sleep ( 0.1 )
pbar . update ( 10 )
pbar . close ()
Talvez o uso mais maravilhoso do tqdm
seja em um script ou na linha de comando. Simplesmente inserir tqdm
(ou python -m tqdm
) entre pipes passará por todos stdin
para stdout
enquanto imprime o progresso para stderr
.
O exemplo abaixo demonstra a contagem do número de linhas em todos os arquivos Python no diretório atual, com informações de tempo incluídas.
$ 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
Observe que os argumentos usuais para tqdm
também podem ser especificados.
$ 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]
Fazendo backup de um diretório grande?
$ tar -zcf - docs/ | tqdm --bytes --total ` du -sb docs/ | cut -f1 `
> backup.tgz
44% | ██████████████▊ | 153M/352M [00: 14< 00:18, 11.0MB/s]
Isso pode ser embelezado ainda mais:
$ 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]
Ou feito em nível de arquivo usando 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]
Programas CLI pré-existentes que já geram informações básicas de progresso se beneficiarão dos sinalizadores --update
e --update_to
do 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]
Os problemas mais comuns estão relacionados à produção excessiva em várias linhas, em vez de uma barra de progresso organizada de uma linha.
CR
, r
).r
adequadamente (cloudwatch, K8s) podem se beneficiar da export TQDM_POSITION=-1
.colorama
para garantir que as barras aninhadas permaneçam dentro de suas respectivas linhas.ascii
.tqdm
não.tqdm(enumerate(...))
por enumerate(tqdm(...))
ou tqdm(enumerate(x), total=len(x), ...)
. O mesmo se aplica a numpy.ndenumerate
.tqdm(zip(a, b))
por zip(tqdm(a), b)
ou mesmo zip(tqdm(a), tqdm(b))
.itertools
.tqdm.contrib
.docker-compose run
em vez de docker-compose up
e tty: true
.export TQDM_MININTERVAL=5
para evitar spam de log. Essa lógica de substituição é tratada pelo decorador tqdm.utils.envwrap
(útil independente de tqdm
).Se você encontrar alguma outra dificuldade, navegue e arquive o arquivo .
(Desde 19 de maio de 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 ):
Iterável para decorar com uma barra de progresso. Deixe em branco para gerenciar manualmente as atualizações.
Prefixo para a barra de progresso.
O número de iterações esperadas. Se não for especificado, len(iterable) será usado, se possível. Se float("inf") ou como último recurso, apenas estatísticas básicas de progresso serão exibidas (sem ETA, sem barra de progresso). Se gui
for True e este parâmetro precisar de atualização subseqüente, especifique um grande número positivo inicial arbitrário, por exemplo, 9e9.
Se [padrão: True], mantém todos os rastreamentos da barra de progresso após o término da iteração. Se None
, sairá apenas se position
for 0
.
io.TextIOWrapper
ou io.StringIO
, opcional Especifica onde gerar as mensagens de progresso (padrão: sys.stderr). Usa os métodos file.write(str)
e file.flush()
. Para codificação, consulte write_bytes
.
A largura de toda a mensagem de saída. Se especificado, redimensiona dinamicamente a barra de progresso para permanecer dentro deste limite. Se não for especificado, tenta usar a largura do ambiente. O substituto tem uma largura de 10 metros e não há limite para o contador e estatísticas. Se for 0, não imprimirá nenhum medidor (apenas estatísticas).
Intervalo mínimo de atualização da exibição do progresso [padrão: 0,1] segundos.
Intervalo máximo de atualização da exibição do progresso [padrão: 10] segundos. Ajusta automaticamente miniters
para corresponder ao mininterval
após um longo atraso de atualização do display. Funciona apenas se dynamic_miniters
ou thread de monitor estiverem habilitados.
Intervalo mínimo de atualização da exibição do progresso, em iterações. Se 0 e dynamic_miniters
, será ajustado automaticamente para mininterval
igual (mais eficiente da CPU, bom para loops apertados). Se > 0, pulará a exibição do número especificado de iterações. Ajuste isso e mininterval
para obter loops muito eficientes. Se o seu progresso for irregular com iterações rápidas e lentas (rede, pular itens, etc.), você deve definir miniters=1.
Se não for especificado ou for falso, use Unicode (blocos suaves) para preencher o medidor. A alternativa é usar caracteres ASCII "123456789#".
Se deseja desabilitar todo o wrapper da barra de progresso [padrão: False]. Se definido como Nenhum, desative em não-TTY.
String que será utilizada para definir a unidade de cada iteração [padrão: it].
Se for 1 ou True, o número de iterações será reduzido/escalado automaticamente e um prefixo métrico seguindo o padrão do Sistema Internacional de Unidades será adicionado (quilo, mega, etc.) [padrão: False]. Se houver qualquer outro número diferente de zero, será dimensionado total
e n
.
Se definido, altera constantemente ncols
e nrows
para o ambiente (permitindo redimensionamento de janelas) [padrão: False].
Fator de suavização de média móvel exponencial para estimativas de velocidade (ignorado no modo GUI). Varia de 0 (velocidade média) a 1 (velocidade atual/instantânea) [padrão: 0,3].
Especifique uma formatação de string de barra personalizada. Pode afetar o desempenho. [padrão: '{l_bar}{bar}{r_bar}'], onde l_bar='{desc}: {percentage:3.0f}%|' e r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, ' '{rate_fmt}{postfix}]' Variáveis possíveis: l_bar, bar, r_bar, n, n_fmt, total, total_fmt, percentage, elapsed, elapsed_s, ncols , nrows, desc, unidade, taxa, taxa_fmt, taxa_noinv, taxa_noinv_fmt, taxa_inv, taxa_inv_fmt, postfix, unit_divisor, restante, restante_s, eta. Observe que um ":" à direita é removido automaticamente após {desc} se este estiver vazio.
O valor inicial do contador. Útil ao reiniciar uma barra de progresso [padrão: 0]. Se estiver usando float, considere especificar {n:.3f}
ou similar em bar_format
ou especificar unit_scale
.
Especifique o deslocamento da linha para imprimir esta barra (começando em 0). Automático se não for especificado. Útil para gerenciar múltiplas barras ao mesmo tempo (por exemplo, de threads).
*
, opcional Especifique estatísticas adicionais para exibir no final da barra. Chama set_postfix(**postfix)
se possível (dict).
[padrão: 1000], ignorado, a menos que unit_scale
seja True.
Se deve escrever bytes. If (padrão: False) escreverá unicode.
Passado para refresh
para saída intermediária (inicialização, iteração e atualização).
A altura da tela. Se especificado, oculta as barras aninhadas fora deste limite. Se não for especificado, tenta usar a altura do ambiente. O substituto é 20.
Cor da barra (por exemplo, 'verde', '#00ff00').
Não exibir até que [padrão: 0] segundos tenham decorrido.
delim
é especificado.delim
e padronizará unit_scale
como True, unit_divisor
como 1024 e unit
como 'B'.stdin
para stderr
e stdout
.update()
. Observe que isso é lento (~2e5 it/s), pois cada entrada deve ser decodificada como um número.self.n
. Observe que isso é lento (~2e5 it/s), pois cada entrada deve ser decodificada como um número. 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
O pacote tqdm.contrib
também contém módulos experimentais:
tqdm.contrib.itertools
: wrappers finos em torno de itertools
tqdm.contrib.concurrent
: wrappers finos em torno de concurrent.futures
tqdm.contrib.slack
: postagens para bots do Slacktqdm.contrib.discord
: Postagens para bots Discordtqdm.contrib.telegram
: Postagens para bots do Telegramtqdm.contrib.bells
: ativa automaticamente todos os recursos opcionaisauto
, pandas
, slack
, discord
, telegram
help()
; Informações personalizadas podem ser exibidas e atualizadas dinamicamente nas barras tqdm
com os argumentos desc
e 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 ()
Pontos a serem lembrados ao usar {postfix[...]}
na string bar_format
:
postfix
também precisa ser passado como argumento inicial em um formato compatível, epostfix
será convertido automaticamente em uma string se for um objeto semelhante dict
. Para evitar esse comportamento, insira um item extra no dicionário onde a chave não seja uma string. Parâmetros bar_format
adicionais também podem ser definidos substituindo format_dict
, e a própria barra pode ser modificada usando 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 (