tqdm
源自阿拉伯語單字taqaddum (Yuقdeّm),意思是“進步”,是西班牙語“我非常愛你”的縮寫 ( 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 奈秒( tqdm.gui
為 80 奈秒),並且針對效能回歸進行了單元測試。相比之下,成熟的 ProgressBar 的開銷為 800ns/iter。
除了較低的開銷之外, tqdm
還使用智慧演算法來預測剩餘時間並跳過不必要的迭代顯示,這在大多數情況下允許忽略不計的開銷。
tqdm
可在任何平台(Linux、Windows、Mac、FreeBSD、NetBSD、Solaris/SunOS)、任何控制台或 GUI 中工作,並且對 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
tab 補全。
docker pull tqdm/tqdm
docker run -i --rm tqdm/tqdm --help
還有其他(非官方)地方可以下載tqdm
,特別是 CLI 使用:
所有更改的清單均可在 GitHub 的版本:、wiki 或網站上找到。
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 )
使用with
語句手動控制tqdm()
更新:
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 程式將受益於tqdm
的--update
和--update_to
標誌:
$ 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
以確保巢狀條形保持在各自的行內。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
有用)。如果您遇到任何其他困難,請瀏覽並歸檔。
(自2016年5月19日起)
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
(CPU 效率較高,有利於緊密循環)。如果 > 0,將跳過指定迭代次數的顯示。調整這個和mininterval
以獲得非常有效的循環。如果你的進度在快速和慢速迭代(網路、跳過項目等)中都不穩定,你應該設定 minters=1。
如果未指定或為 False,則使用 unicode(平滑區塊)來填入儀表。後備方法是使用 ASCII 字元“123456789#”。
是否停用整個進度條包裝器[預設值:False]。如果設定為“無”,則在非 TTY 上停用。
將用於定義每次迭代的單位的字串[預設值:it]。
如果為 1 或 True,則迭代次數將自動減少/縮放,並添加遵循國際單位制標準的公制前綴(千、兆等)[預設值:False]。如果有任何其他非零數字,將縮放total
和n
。
如果設置,則不斷更改環境中的ncols
和nrows
(允許調整視窗大小)[預設值:False]。
用於速度估計的指數移動平均平滑因子(在 GUI 模式下被忽略)。範圍從 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、percentage、elapsed、elapsed_s、elapsed_s、 ncols 、nrows、desc、單位、速率、rate_fmt、rate_noinv、rate_noinv_fmt、rate_inv、rate_inv_fmt、後綴、unit_divisor、剩餘、剩餘_s、eta。請注意,如果 {desc} 為空,則後面的「:」會自動刪除。
初始計數器值。重新啟動進度條時很有用[預設值:0]。如果使用 float,請考慮在bar_format
中指定{n:.3f}
或類似內容,或指定unit_scale
。
指定列印此條的行偏移量(從 0 開始)如果未指定則自動。對於一次管理多個欄位很有用(例如,從執行緒)。
*
,可選指定要在欄位末尾顯示的其他統計資料。如果可能的話,呼叫set_postfix(**postfix)
(dict)。
[預設值:1000],除非unit_scale
為 True,否則將被忽略。
是否寫入位元組。如果(預設值:False)將寫入 unicode。
傳遞給中間輸出的refresh
(初始化、迭代和更新)。
螢幕高度。如果指定,則隱藏此邊界以外的巢狀欄。如果未指定,則嘗試使用環境高度。後備值為 20。
條形顏色(例如“綠色”、“#00ff00”)。
在 [預設值:0] 秒過去之前不顯示。
delim
時使用的字串緩衝區大小(以位元組為單位)[預設值:256]。delim
,並將預設的unit_scale
設為True, unit_divisor
1024,將unit
設為「B」。stdin
傳遞給stderr
和stdout
。update()
數字。請注意,這很慢(~2e5 it/s),因為每個輸入都必須解碼為數字。self.n
數字。請注意,這很慢(~2e5 it/s),因為每個輸入都必須解碼為數字。 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()
;可以使用desc
和postfix
參數在tqdm
欄上動態顯示和更新自訂資訊:
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 ()
在bar_format
字串中使用{postfix[...]}
時要記住的重點:
postfix
也需要以相容的格式作為初始參數傳遞,並且postfix
是類似dict
對象,它會自動轉換為字串。為了防止這種行為,請在字典中插入一個額外的項目,其中鍵不是字串。額外的bar_format
參數也可以透過覆寫format_dict
來定義,而 bar 本身可以使用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 (