tqdm學習-一個快速,可擴展的Python和CLI進度條

參考:https://pypi.org/project/tqdm/html

1.安裝:前端

(base) userdeMacBook-Pro:~ user$ conda activate deeplearning
(deeplearning) userdeMacBook-Pro:~ user$ conda install -c conda-forge tqdm
 
Collecting package metadata: done
Solving environment: done

## Package Plan ##

  environment location: /anaconda3/envs/deeplearning

  added / updated specs:
    - tqdm

...
Downloading and Extracting Packages
python-1.6           | 3.7 MB    | ##################################### | 100% 
tqdm-4.35.0          | 42 KB     | ##################################### | 100% 
decorator-4.4.0      | 13 KB     | ##################################### | 100% 
ca-certificates-2019 | 143 KB    | ##################################### | 100% 
openssl-1.1.1c       | 1.9 MB    | ##################################### | 100% 
Preparing transaction: done
Verifying transaction: done
Executing transaction: done

使用這個方法安裝好像將我conda的環境的python版本換成了1.6版本,很差:python

(deeplearning) userdeMBP:bin user$ jupyter notebook
Traceback (most recent call last):
  File "/anaconda3/envs/deeplearning/bin/jupyter", line 7, in <module>
    from jupyter_core.command import main
ModuleNotFoundError: No module named 'jupyter_core'

解決,回到原來的狀態:git

(deeplearning) userdeMBP:bin user$ conda uninstall tqdm
Collecting package metadata: done
Solving environment: done

## Package Plan ##

  environment location: /anaconda3/envs/deeplearning

  removed specs:
    - tqdm


The following packages will be REMOVED:

  tqdm-4.35.0-py_0


Proceed ([y]/n)? y

Preparing transaction: done
Verifying transaction: done
Executing transaction: done
(deeplearning) userdeMBP:bin user$ conda update python
The following packages will be UPDATED:

  certifi                pkgs/main::certifi-2019.3.9-py36_0 --> conda-forge::certifi-2019.9.11-py37_0
  python                                              1.6-0 --> 3.7.3-h93065d6_1
  readline               pkgs/main::readline-7.0-h1de35cc_5 --> conda-forge::readline-8.0-hcfe32e1_0
  sqlite                pkgs/main::sqlite-3.27.2-ha441bb4_0 --> conda-forge::sqlite-3.29.0-hb7d70f7_1
  tk                         pkgs/main::tk-8.6.8-ha441bb4_0 --> conda-forge::tk-8.6.9-h2573ce8_1003
  wheel              anaconda/pkgs/main::wheel-0.33.1-py36~ --> conda-forge::wheel-0.33.6-py37_0

在anaconda上從新安裝下jupyter notebook便可github

 

換成了下面的下載方法:sql

(base) userdembp:bin user$ conda activate deeplearning3.5
(deeplearning3.5) userdembp:bin user$ pip install -e git+https://github.com/tqdm/tqdm.git@master#egg=tqdm
Obtaining tqdm from git+https://github.com/tqdm/tqdm.git@master#egg=tqdm
  Cloning https://github.com/tqdm/tqdm.git (to revision master) to ./src/tqdm
Installing collected packages: tqdm
  Running setup.py develop for tqdm
Successfully installed tqdm
You are using pip version 19.0.3, however version 19.2.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

 

2.使用網絡

tqdm是通用的,能以不少種方式使用。下面給出主要的三種方式:多線程

1)基於迭代器的方法:併發

即將tqdm封裝在任意迭代器中app

# conding:utf-8
from tqdm import tqdm
import time

text = ""
for char in tqdm(["a", "b", "c", "d"]):
    time.sleep(0.25)
    text = text + char
print(text)

運行返回:

/anaconda3/envs/deeplearning3.5/bin/python3.5 /Users/user/PycharmProjects/new/learning.py
 75%|███████▌  | 3/4 [00:00<00:00,  3.97it/s]abcd
100%|██████████| 4/4 [00:01<00:00,  3.96it/s]

Process finished with exit code 0

 

tqdm(range(i))可使用trange(i)替換:

# conding:utf-8
from tqdm import tqdm
import time

text = 0
for i in tqdm(range(10)):
    time.sleep(0.25)
    text += i
print(text)

返回:

/anaconda3/envs/deeplearning3.5/bin/python3.5 /Users/user/PycharmProjects/new/learning.py
100%|██████████| 10/10 [00:02<00:00,  3.96it/s]
45

Process finished with exit code 0

等價於:

# conding:utf-8
from tqdm import trange
import time

text = 0
for i in trange(10):
    time.sleep(0.25)
    text += i
print(text)

返回:

/anaconda3/envs/deeplearning3.5/bin/python3.5 /Users/user/PycharmProjects/new/learning.py
 90%|█████████ | 9/10 [00:02<00:00,  3.96it/s]45
100%|██████████| 10/10 [00:02<00:00,  3.96it/s]

Process finished with exit code 0

 

在循環外面實例化可以實現tqdm()的手動控制:

# conding:utf-8
from tqdm import tqdm
import time

pbar = tqdm(["a", "b", "c", "d"])
for char in pbar:
    time.sleep(0.25)
    pbar.set_description("processing %s" % char)

返回:

/anaconda3/envs/deeplearning3.5/bin/python3.5 /Users/user/PycharmProjects/new/learning.py
processing d: 100%|██████████| 4/4 [00:01<00:00,  3.95it/s]

Process finished with exit code 0

前四步是processing a,processing b,processing c

 

2)手動控制

經過使用with語句來實現tqdm()的手動控制:

# conding:utf-8
from tqdm import tqdm
import time

with tqdm(total=100) as pbar:
    for i in range(10):
        time.sleep(0.1)
        pbar.update(10)

返回:

/anaconda3/envs/deeplearning3.5/bin/python3.5 /Users/user/PycharmProjects/new/learning.py
100%|██████████| 100/100 [00:01<00:00, 97.06it/s]

Process finished with exit code 0

 

若是提供了可選變量total(或者如len()的可迭代函數),就會顯示預測狀態

with語句也是可選的(你也能夠直接賦值tqdm()到一個變量上,重點就在於你不要忘記了在最後的時候手動del或closr()它),使用with的好處就是它會在最後自動關閉

# conding:utf-8
from tqdm import tqdm
import time

pbar = tqdm(total=100)
for i in range(10):
    time.sleep(0.1)
    pbar.update(10)
pbar.close()

返回:

/anaconda3/envs/deeplearning3.5/bin/python3.5 /Users/user/PycharmProjects/new/learning.py
100%|██████████| 100/100 [00:01<00:00, 97.40it/s]

Process finished with exit code 0

 

3)模塊

可能tqdm最優美的使用就是在腳本或命令行中。簡單在管道中插入tqdm(或者命令python -m tqdm),這樣在打印過程到stderr時將傳遞全部stdin到stdout

下面的例子闡述了在當前目錄中計算全部python文件中的行數的例子,而且包含這相應的記時信息:

(deeplearning3.5) userdembp:new user$ time find . -name '*.py' -type f -exec cat \{} \; | wc -l
       8

real    0m0.015s
user    0m0.004s
sys     0m0.009s
(deeplearning3.5) userdembp:new user$ time find . -name '*.py' -type f -exec cat \{} \; | tqdm | wc -l
9it [00:00, 49998.33it/s]
       8

real    0m0.273s
user    0m0.207s
sys     0m0.053s
(deeplearning3.5) userdembp:new user$ 

此時該目錄下就只有一個learning.py文件,裏面的代碼爲:

# conding:utf-8
from tqdm import tqdm
import time

pbar = tqdm(total=100)
for i in range(10):
    time.sleep(0.1)
    pbar.update(10)
pbar.close()

可見除去空行的確是8行

 

注意tqdm一般使用的參數也可以指定:

(deeplearning3.5) userdembp:new user$ time find . -name '*.py' -type f -exec cat \{} \; | tqdm -unit loc --unit_scale --total 8 >> out.log
9.00loc [00:00, 33.6kloc/s]                                                                                                                                              

real    0m0.383s
user    0m0.218s
sys     0m0.076s
(deeplearning3.5) userdembp:new user$ ls
learning.py     out.log
(deeplearning3.5) userdembp:new user$ cat out.log
# conding:utf-8
from tqdm import tqdm
import time

pbar = tqdm(total=100)
for i in range(10):
    time.sleep(0.1)
    pbar.update(10)
pbar.close()

這裏即將單位換成loc,而後將獲得的內容輸入到out.log文件夾中

 

4)文檔

class tqdm():
  """
  裝飾一個迭代器對象,返回一個表現得就像原來可迭代的迭代器;可是在每次值被請求時就打印一個動態的更新進度條
  """

  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):

參數:

  • iterable : iterable, optional:使用一個進度條可迭代地去裝飾。留下空白去手動處理更新
  • desc : str, optional:進度條的前綴
  • total : int, optional:期待的迭代數。若是不指定的話,就等價於len(iterable)。若是設置爲float("inf")或者萬不得已時,只有基本的進程統計會展現出來(無ETA,也無進度條)。若是gui=True,且該參數須要子序列去更新,指定一個初始的大的隨機正整數便可,如int(9e9)
  • leave : bool, optional:默認爲True,即在迭代的最後保持進度條的全部蹤影,簡單來講就是會把進度條的最終形態保留下來。若是爲None,則僅在position=0時保留下來,即保留第一個
  • file : io.TextIOWrapper or io.StringIO, optional:指定輸出進程信息的地方,默認爲sys.stderr。使用file.write(str)和file.flush()方法。對於encoding編碼,可見write_bytes
  • ncols : int, optional:整個輸出信息的寬度。若是指定,將在動態地從新設置進度條的大小來將其保留在這樣的邊界中。若是沒有指定,就會嘗試去使用環境設置的寬度。回退的計量寬度爲10,計數器和統計數據的大小沒有限制
  • mininterval : float, optional:顯示更新間隔[默認值:0.1]秒的最小進度,即更新時間
  • maxinterval : float, optional:顯示更新間隔[默認值:10]秒的最大進度。通過長時間的顯示更新滯後時會自動調整miniters參數來對應mininterval參數。只有在設置dynamic_miniters=True或顯示線程開啓時才工做
  • miniters : int, optional:即在迭代中顯示更新間隔的最小進度,即更新週期。若是設置爲0或dynamic_miniters=True時就會自動調整和mininterval同樣大(CPU效率更高,適合緊湊的循環)。若是設置>0,將跳過特定迭代數的顯示。可以經過調整這個和mininterval參數去得到高效的循環。若是你的進度不穩定,迭代速度有快有慢(網絡、跳過項目等),您應該將miniter設置爲1。若是設置了該值,mininterval則會自動設爲0
  • ascii : bool or str, optional:若是沒有指定或者設置爲False,將會使用unicode編碼(光滑的塊)去填補計量。回退使用的是ASCII字符 」 123456789#」
  • disable : bool, optional:是否不使用整個進度條的封裝,默認爲False,即便用封裝。若是設置爲None,則在non-TTY時不使用
  • unit : str, optional:用來定義每一個迭代單元的字符串。默認爲"it",表示每一個迭代;在下載或解壓時,設爲"B",表明每一個「塊」。
  • unit_scale : bool or int or float, optional:若是設置爲1或者True,迭代數量就會被自動減小或者重置,且將在國際單位制標準後面添加一個度量前綴(kilo、mega等)[默認:False],其實就是若是迭代數過大,它就會自動在後面加上M、k等字符來表示迭代進度等,好比,在下載進度條的例子中,若是爲False,數據大小是按照字節顯示,設爲True以後轉換爲Kb、Mb
  • dynamic_ncols : bool, optional:若是設置了,就會不斷地更換環境的ncols參數(容許用於窗口大小重置),默認爲False
  • smoothing : float, optional:速度估計的指數移動平均平滑因子(在GUI模式中忽略)。範圍從0(平均速度)到1(當前/瞬時速度)[默認值:0.3]。
  • bar_format : str, optional:指定自定義進度欄字符串格式。可能會影響性能。(默認值: ‘{l_bar}{bar}{r_bar}’), l_bar = ’{desc}: {percentage:3.0f}%|’和r_bar = ’| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, ‘ ‘{rate_fmt}{postfix}]’ 可能的var爲: l_bar, bar, r_bar, n, n_fmt, total, total_fmt, percentage, rate, rate_fmt, rate_noinv, rate_noinv_fmt, rate_inv, rate_inv_fmt, elapsed, elapsed_s, remaining, remaining_s, desc, postfix, unit。注意,若是{desc}後面是空的,那麼其後面的「:」將自動刪除。
  • initial : int, optional:初始計數器值。在從新啓動進度條時有用[默認值:0]。
  • position : int, optional:若是未指定,請指定要自動打印此欄的行偏移量(從0開始)。對於一次管理多個進度條是有用的(如線程)。
  • postfix : dict or *, optional:指定要在進度欄末顯示的其餘統計信息。若是可能(dict),調用set_postfix(**postfix) 。
  • unit_divisor : float, optional:默認爲1000,若是unit_scale=True,則忽略它
  • write_bytes : bool, optional:若是爲默認值None和file未指定時,字節將會被寫在python2中。若是設置爲True,也是寫成字節。在其餘的狀況下則默認寫成unicode格式
額外的CLI可選項:
  • delim : chr, optional:分隔字符[默認值:' n ']。使用「0」表示null。注意::在Windows系統中,Python將「n」轉換爲「rn」。
  • buf_size : int, optional:指定delim時使用的以字節爲單位的字符串緩衝區大小[默認值:256]。
  • bytes : bool, optional:若是爲真,將計數字節,忽略delim參數,並默認unit_scale爲真,unit_divisor爲1024,unit爲' B '。
  • manpath : str, optional:安裝tqdm手冊頁的目錄。
  • log : str, optional:打印的日誌信息類別,CRITICAL|FATAL|ERROR|WARN(ING)|[default: ‘INFO’]|DEBUG|NOTSET,默認爲INFO
返回:
裝飾後的迭代器
class tqdm():
  def update(self, n=1):
      """
      手動更新進度條,對流streams有用,好比讀文件
      E.g.:
      >>> t = tqdm(total=filesize) # Initialise
      >>> for current_buffer in stream:
      ...    ...
      ...    t.update(len(current_buffer))
      >>> t.close()
      最後一行高度推薦使用,可是若是``t.update()`` 是在``filesize``即將徹底到達和打印時調用的話可能就不須要

      Parameters
      ----------
      n  : int, optional
            添加到迭代內部計數器的增加數[default: 1]
      """

  def close(self):
      """清除(if leave=False)和關閉進度條"""

  def clear(self, nomove=False):
      """清除當前的進度條顯示."""

  def refresh(self):
      """強迫更新該進度條的顯示Force refresh the display of this bar."""

  def unpause(self):
      """從最新運行時間重啓tqdm計時器"""

  def reset(self, total=None):
      """
      爲了重複使用,重設爲第0次迭代。考慮和``leave=True``設置一塊兒使用

      Parameters
      ----------
      total  : int, optional. 用於新進度條的次數.
      """

  def set_description(self, desc=None, refresh=True):
      """
      設置/修改進度條的描述格式

      Parameters
      ----------
      desc  : str, optional
      refresh  : bool, optional
          Forces refresh [default: True].
      """

  def set_postfix(self, ordered_dict=None, refresh=True, **kwargs):
      """
      設置/修改後綴(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"):
      """經過tqdm打印信息(不覆蓋進度條)."""

  @property
  def format_dict(self):
      """給只讀權限人員訪問的公用API"""

  def display(self, msg=None, pos=None):
      """
      使用``self.sp`` 去展現指定``pos``中的``msg``.

      當繼承使用時,要考慮重載該函數 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)``).
      """

def trange(*args, **kwargs):
    """
    tqdm(xrange(*args), **kwargs)函數的縮寫
    Python3+版本中使用 range來替換 xrange.
    """

class tqdm_gui(tqdm):
    """Experimental GUI version"""

def tgrange(*args, **kwargs):
    """Experimental GUI version of trange"""

class tqdm_notebook(tqdm):
    """Experimental IPython/Jupyter Notebook widget"""

def tnrange(*args, **kwargs):
    """Experimental IPython/Jupyter Notebook widget version of trange"""

 

Examples and Advanced Usage

"""
# Simple tqdm examples and profiling
# Benchmark
for i in _range(int(1e8)):
    pass
# Basic demo
import tqdm
for i in tqdm.trange(int(1e8)):
    pass
# Some decorations
import tqdm
for i in tqdm.trange(int(1e8), miniters=int(1e6), ascii=True,
                     desc="cool", dynamic_ncols=True):
    pass
# Nested bars
from tqdm import trange
for i in trange(10):
    for j in trange(int(1e7), leave=False, unit_scale=True):
        pass
# Experimental GUI demo
import tqdm
for i in tqdm.tgrange(int(1e8)):
    pass
# Comparison to https://code.google.com/p/python-progressbar/
try:
    from progressbar.progressbar import ProgressBar
except ImportError:
    pass
else:
    for i in ProgressBar()(_range(int(1e8))):
        pass
# Dynamic miniters benchmark
from tqdm import trange
for i in trange(int(1e8), miniters=None, mininterval=0.1, smoothing=0):
    pass
# Fixed miniters benchmark
from tqdm import trange
for i in trange(int(1e8), miniters=4500000, mininterval=0.1, smoothing=0):
    pass
"""

from time import sleep
from timeit import timeit
import re

# Simple demo
from tqdm import trange
for i in trange(16, leave=True):
    sleep(0.1)

# Profiling/overhead tests
stmts = filter(None, re.split(r'\n\s*#.*?\n', __doc__))
for s in stmts:
    print(s.replace('import tqdm\n', ''))
    print(timeit(stmt='try:\n\t_range = xrange'
                 '\nexcept:\n\t_range = range\n' + s, number=1), 'seconds')

一個個分析:

"""
# Simple tqdm examples and profiling
# Benchmark
for i in _range(int(1e8)):
    pass

"""

from time import sleep
from timeit import timeit
import re

# Simple demo
from tqdm import trange
for i in trange(16, leave=True):
    sleep(0.1)

# Profiling/overhead tests
stmts = filter(None, re.split(r'\n\s*#.*?\n', __doc__))
for s in stmts:
    print(s.replace('import tqdm\n', ''))
    print(timeit(stmt='try:\n\t_range = xrange'
                 '\nexcept:\n\t_range = range\n' + s, number=1), 'seconds')

返回:

100%|██████████| 16/16 [00:01<00:00,  9.59it/s]
# Benchmark
for i in _range(int(1e8)):
    pass


2.328720851000071 seconds

 

下面都同樣,僅運行一個來分析學習

1)

"""
# Simple tqdm examples and profiling
# Basic demo
import tqdm
for i in tqdm.trange(int(1e8)):
    pass

"""

返回:

100%|██████████| 16/16 [00:01<00:00,  9.65it/s]
  0%|          | 301598/100000000 [00:00<00:33, 3015975.69it/s]
# Basic demo
for i in tqdm.trange(int(1e8)):
    pass


100%|██████████| 100000000/100000000 [00:18<00:00, 5407942.99it/s]
18.4932925789999 seconds

 

2)

"""
# Simple tqdm examples and profiling
# Some decorations
import tqdm
for i in tqdm.trange(int(1e8), miniters=int(1e6), ascii=True,
                     desc="cool", dynamic_ncols=True):
    pass

"""

中間:

 返回:

100%|██████████| 16/16 [00:01<00:00,  9.71it/s]
cool:   0%|          | 0/100000000 [00:00<?, ?it/s]
# Some decorations
for i in tqdm.trange(int(1e8), miniters=int(1e6), ascii=True,
                     desc="cool", dynamic_ncols=True):
    pass


cool: 100%|##########| 100000000/100000000 [00:17<00:00, 5650878.97it/s]
17.699349756000174 seconds

 

3)

"""
# Simple tqdm examples and profiling
# Nested bars
from tqdm import trange
for i in trange(2): 
    for j in trange(int(1e7), leave=False, unit_scale=True):
        pass

"""

返回:

100%|██████████| 16/16 [00:01<00:00,  9.76it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0.00/10.0M [00:00<?, ?it/s]
  3%|▎         | 327k/10.0M [00:00<00:02, 3.27Mit/s]
# Nested bars
from tqdm import trange
for i in trange(2):
    for j in trange(int(1e7), leave=False, unit_scale=True):
        pass



  7%|▋         | 667k/10.0M [00:00<00:02, 3.31Mit/s]
 10%|█         | 1.04M/10.0M [00:00<00:02, 3.43Mit/s]
 13%|█▎        | 1.34M/10.0M [00:00<00:02, 3.27Mit/s]
 17%|█▋        | 1.70M/10.0M [00:00<00:02, 3.38Mit/s]
 21%|██        | 2.11M/10.0M [00:00<00:02, 3.56Mit/s]
 25%|██▌       | 2.55M/10.0M [00:00<00:01, 3.77Mit/s]
 30%|██▉       | 2.99M/10.0M [00:00<00:01, 3.93Mit/s]
 34%|███▍      | 3.44M/10.0M [00:00<00:01, 4.11Mit/s]
 39%|███▉      | 3.91M/10.0M [00:01<00:01, 4.27Mit/s]
 44%|████▍     | 4.39M/10.0M [00:01<00:01, 4.41Mit/s]
 49%|████▉     | 4.88M/10.0M [00:01<00:01, 4.54Mit/s]
 54%|█████▍    | 5.38M/10.0M [00:01<00:00, 4.67Mit/s]
 59%|█████▊    | 5.87M/10.0M [00:01<00:00, 4.74Mit/s]
 64%|██████▎   | 6.35M/10.0M [00:01<00:00, 4.77Mit/s]
 68%|██████▊   | 6.83M/10.0M [00:01<00:00, 4.76Mit/s]
 73%|███████▎  | 7.31M/10.0M [00:01<00:00, 4.64Mit/s]
 78%|███████▊  | 7.77M/10.0M [00:01<00:00, 4.48Mit/s]
 82%|████████▏ | 8.22M/10.0M [00:01<00:00, 4.44Mit/s]
 87%|████████▋ | 8.71M/10.0M [00:02<00:00, 4.55Mit/s]
 92%|█████████▏| 9.20M/10.0M [00:02<00:00, 4.67Mit/s]
 97%|█████████▋| 9.68M/10.0M [00:02<00:00, 4.69Mit/s]
 50%|█████     | 1/2 [00:02<00:02,  2.30s/it]        
  0%|          | 0.00/10.0M [00:00<?, ?it/s]
  3%|▎         | 296k/10.0M [00:00<00:03, 2.96Mit/s]
  6%|▌         | 586k/10.0M [00:00<00:03, 2.94Mit/s]
  9%|▉         | 896k/10.0M [00:00<00:03, 2.99Mit/s]
 12%|█▏        | 1.24M/10.0M [00:00<00:02, 3.10Mit/s]
 16%|█▌        | 1.59M/10.0M [00:00<00:02, 3.21Mit/s]
 19%|█▉        | 1.94M/10.0M [00:00<00:02, 3.31Mit/s]
 23%|██▎       | 2.33M/10.0M [00:00<00:02, 3.46Mit/s]
 27%|██▋       | 2.71M/10.0M [00:00<00:02, 3.57Mit/s]
 31%|███       | 3.12M/10.0M [00:00<00:01, 3.69Mit/s]
 35%|███▌      | 3.53M/10.0M [00:01<00:01, 3.81Mit/s]
 39%|███▉      | 3.93M/10.0M [00:01<00:01, 3.88Mit/s]
 44%|████▍     | 4.40M/10.0M [00:01<00:01, 4.08Mit/s]
 49%|████▉     | 4.88M/10.0M [00:01<00:01, 4.27Mit/s]
 54%|█████▍    | 5.38M/10.0M [00:01<00:01, 4.48Mit/s]
 59%|█████▊    | 5.87M/10.0M [00:01<00:00, 4.60Mit/s]
 64%|██████▍   | 6.38M/10.0M [00:01<00:00, 4.72Mit/s]
 69%|██████▉   | 6.90M/10.0M [00:01<00:00, 4.85Mit/s]
 74%|███████▍  | 7.41M/10.0M [00:01<00:00, 4.93Mit/s]
 79%|███████▉  | 7.92M/10.0M [00:01<00:00, 4.98Mit/s]
 84%|████████▍ | 8.42M/10.0M [00:02<00:00, 4.74Mit/s]
 89%|████████▉ | 8.90M/10.0M [00:02<00:00, 4.77Mit/s]
 94%|█████████▍| 9.40M/10.0M [00:02<00:00, 4.84Mit/s]
 99%|█████████▉| 9.93M/10.0M [00:02<00:00, 4.95Mit/s]
100%|██████████| 2/2 [00:04<00:00,  2.32s/it]        
4.642330375000256 seconds

⚠️這裏返回[00:00<00:03, 2.96Mit/s]中前面的00:00表示已用時間,以秒爲單位,因此在1秒前都爲0,<後面的00:03表示剩餘須要花的時間,2.96Mit/s表示速度

 

刪掉參數unit_scale=True:

返回可見設置時使用M單位簡化數字:

100%|██████████| 16/16 [00:01<00:00,  9.64it/s]
  0%|          | 0/1 [00:00<?, ?it/s]
  0%|          | 0/10000000 [00:00<?, ?it/s]
  3%|▎         | 277015/10000000 [00:00<00:03, 2770126.22it/s]
# Nested bars
from tqdm import trange
for i in trange(1): 
    for j in trange(int(1e7), leave=False):
        pass



  6%|▌         | 558583/10000000 [00:00<00:03, 2783635.65it/s]
  9%|▉         | 895786/10000000 [00:00<00:03, 2937395.56it/s]
 13%|█▎        | 1258399/10000000 [00:00<00:02, 3114883.50it/s]
 17%|█▋        | 1667463/10000000 [00:00<00:02, 3354857.99it/s]
 21%|██        | 2105227/10000000 [00:00<00:02, 3607718.69it/s]
 26%|██▌       | 2551042/10000000 [00:00<00:01, 3826706.29it/s]
 30%|███       | 3028044/10000000 [00:00<00:01, 4068052.94it/s]
 35%|███▌      | 3502923/10000000 [00:00<00:01, 4250850.87it/s]
 40%|███▉      | 3975152/10000000 [00:01<00:01, 4382092.05it/s]
 44%|████▍     | 4444320/10000000 [00:01<00:01, 4470580.81it/s]
 49%|████▉     | 4913953/10000000 [00:01<00:01, 4535991.51it/s]
 54%|█████▍    | 5412819/10000000 [00:01<00:00, 4662832.67it/s]
 59%|█████▉    | 5903458/10000000 [00:01<00:00, 4733320.55it/s]
 64%|██████▍   | 6407480/10000000 [00:01<00:00, 4821381.19it/s]
 69%|██████▉   | 6890932/10000000 [00:01<00:00, 4732373.17it/s]
 74%|███████▎  | 7365457/10000000 [00:01<00:00, 4589660.71it/s]
 78%|███████▊  | 7828722/10000000 [00:01<00:00, 4602468.26it/s]
 83%|████████▎ | 8290265/10000000 [00:01<00:00, 4587601.91it/s]
 88%|████████▊ | 8799822/10000000 [00:02<00:00, 4729019.14it/s]
 93%|█████████▎| 9297792/10000000 [00:02<00:00, 4801530.70it/s]
 98%|█████████▊| 9806813/10000000 [00:02<00:00, 4884621.49it/s]
100%|██████████| 1/1 [00:02<00:00,  2.26s/it]                  
2.264081185000123 seconds

 

設置leave=True,返回:

100%|██████████| 16/16 [00:01<00:00,  9.66it/s]
  0%|          | 0/1 [00:00<?, ?it/s]
  0%|          | 0/10000000 [00:00<?, ?it/s]
  3%|▎         | 322630/10000000 [00:00<00:02, 3226280.00it/s]
# Nested bars
from tqdm import trange
for i in trange(1): 
    for j in trange(int(1e7), leave=True):
        pass



  7%|▋         | 672600/10000000 [00:00<00:02, 3303711.10it/s]
 11%|█         | 1057128/10000000 [00:00<00:02, 3449449.52it/s]
 14%|█▍        | 1427037/10000000 [00:00<00:02, 3520729.15it/s]
 18%|█▊        | 1832741/10000000 [00:00<00:02, 3666110.82it/s]
 22%|██▏       | 2244986/10000000 [00:00<00:02, 3792038.55it/s]
 27%|██▋       | 2691460/10000000 [00:00<00:01, 3971547.54it/s]
 32%|███▏      | 3158486/10000000 [00:00<00:01, 4158176.06it/s]
 36%|███▋      | 3644204/10000000 [00:00<00:01, 4345786.38it/s]
 41%|████      | 4122465/10000000 [00:01<00:01, 4468208.17it/s]
 46%|████▌     | 4612764/10000000 [00:01<00:01, 4590323.02it/s]
 51%|█████     | 5111718/10000000 [00:01<00:01, 4703203.98it/s]
 56%|█████▌    | 5608081/10000000 [00:01<00:00, 4778414.54it/s]
 61%|██████    | 6086716/10000000 [00:01<00:00, 4780780.12it/s]
 66%|██████▌   | 6564640/10000000 [00:01<00:00, 4667924.67it/s]
 70%|███████   | 7031914/10000000 [00:01<00:00, 4532180.69it/s]
 75%|███████▌  | 7521866/10000000 [00:01<00:00, 4636454.48it/s]
 80%|████████  | 8035404/10000000 [00:01<00:00, 4775645.33it/s]
 86%|████████▌ | 8551806/10000000 [00:01<00:00, 4885870.39it/s]
 91%|█████████ | 9066446/10000000 [00:02<00:00, 4961214.82it/s]
100%|██████████| 10000000/10000000 [00:02<00:00, 4552905.40it/s][A
100%|██████████| 1/1 [00:02<00:00,  2.20s/it]
2.2038861539999743 seconds

不一樣在於內部迭代保存最終的結果,即:

100%|██████████| 10000000/10000000 [00:02<00:00, 4552905.40it/s]

 

4)

"""
# Simple tqdm examples and profiling
# Experimental GUI demo
import tqdm
for i in tqdm.tgrange(int(1e8)):
    pass

"""

返回:

100%|██████████| 16/16 [00:01<00:00,  9.69it/s]
# Experimental GUI demo
for i in tqdm.tgrange(int(1e8)):
    pass

19.253753004999908 seconds

圖爲:

 

 5)

"""
# Simple tqdm examples and profiling
# Comparison to https://code.google.com/p/python-progressbar/
try:
    from progressbar.progressbar import ProgressBar
except ImportError:
    pass
else:
    for i in ProgressBar()(_range(int(1e8))):
        pass

"""

返回:

100%|██████████| 16/16 [00:01<00:00,  9.64it/s]
# Comparison to https://code.google.com/p/python-progressbar/
try:
    from progressbar.progressbar import ProgressBar
except ImportError:
    pass
else:
    for i in ProgressBar()(_range(int(1e8))):
        pass


0.0015016719999039196 seconds

 

6)

"""
# Simple tqdm examples and profiling
# Dynamic miniters benchmark
from tqdm import trange
for i in trange(int(1e8), miniters=None, mininterval=0.1, smoothing=0):
    pass

"""

最終:

100%|██████████| 16/16 [00:01<00:00,  9.65it/s]
  0%|          | 313552/100000000 [00:00<00:31, 3134484.22it/s]
# Dynamic miniters benchmark
from tqdm import trange
for i in trange(int(1e8), miniters=None, mininterval=0.1, smoothing=0):
    pass


100%|██████████| 100000000/100000000 [00:16<00:00, 5960460.94it/s]
16.779653078000138 seconds

即mininterval=0.1秒後更新進度欄中的進度

 

若是設置爲miniters=2, mininterval=0

"""
# Simple tqdm examples and profiling
# Dynamic miniters benchmark
from tqdm import trange
for i in trange(int(1e8), miniters=2, mininterval=0):
    pass

"""

返回爲:

 0%|          | 0/100000000 [00:00<?, ?it/s]
  0%|          | 2/100000000 [00:00<06:45, 246723.76it/s]
  0%|          | 4/100000000 [00:00<6:07:28, 4535.36it/s]
  0%|          | 6/100000000 [00:00<15:44:50, 1763.97it/s]
  0%|          | 8/100000000 [00:00<19:05:36, 1454.82it/s]
...

可見每兩個迭代就更新一次

 

若是同時設置了這兩個參數miniters=2, mininterval=1,以大的設置的時間爲主。以下面的這個設置miniters僅爲2,花的時間少,mininterval爲1秒,因此以1秒間隔顯示爲主,忽略miniters設置:

  0%|          | 0/100000000 [00:00<?, ?it/s]
# Dynamic miniters benchmark
from tqdm import trange
for i in trange(int(1e8), miniters=2, mininterval=1):
    pass




  3%|▎         | 3127793/100000000 [00:01<00:30, 3127793.00it/s]

  6%|▌         | 5865282/100000000 [00:02<00:31, 2999494.96it/s]

  9%|▉         | 9147057/100000000 [00:03<00:29, 3078945.08it/s]

 12%|█▏        | 12443754/100000000 [00:04<00:27, 3141189.20it/s]
...

注意:返回[00:01<00:30, 3127793.00it/s]中的00:01表示1秒

 

若是設置爲miniters=4500000, mininterval=0.1,4500000個間隔花的時間更長,因此以迭代數爲主:

  0%|          | 0/100000000 [00:00<?, ?it/s]
# Fixed miniters benchmark
from tqdm import trange
for i in trange(int(1e8), miniters=4500000, mininterval=0.1, smoothing=0):
    pass




  4%|▍         | 4500000/100000000 [00:00<00:16, 5715229.42it/s]

  9%|▉         | 9000000/100000000 [00:01<00:16, 5545180.93it/s]

 14%|█▎        | 13500000/100000000 [00:02<00:15, 5635364.34it/s]

 18%|█▊        | 18000000/100000000 [00:03<00:14, 5656277.70it/s]

 22%|██▎       | 22500000/100000000 [00:03<00:13, 5729412.82it/s]

 27%|██▋       | 27000000/100000000 [00:04<00:12, 5779243.27it/s]

 32%|███▏      | 31500000/100000000 [00:05<00:11, 5820303.28it/s]

 36%|███▌      | 36000000/100000000 [00:06<00:10, 5851854.45it/s]

 40%|████      | 40500000/100000000 [00:06<00:10, 5873663.41it/s]

 45%|████▌     | 45000000/100000000 [00:07<00:09, 5902913.08it/s]
...

 

Description and additional stats

定製信息能夠經過設置desc和postfix參數來動態顯示和更新在tqdm進度欄上:

from tqdm import trange
from random import random, randint
from time import sleep

with trange(10) as t:
    for i in t:
        # 描述將顯示在左邊
        t.set_description('GEN %i' % i)
        # 後綴將顯示在右邊,根據參數的數據類型自動格式化
        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", dict(value=0)]) as t:
    for i in range(10):
        sleep(0.1)
        t.postfix[1]["value"] = i / 2
        t.update()

返回:

GEN 9: 100%|██████████| 10/10 [00:01<00:00,  9.42it/s, gen=356, loss=0.806, lst=[1, 2], str=h]
Batch      4.5

記得在bar_format字符串中使用{postfix[...]}來指向:

  • postfix須要在兼容格式中做爲初始參數傳遞
  • 若是postfix是類字典對象,將自動轉換爲一個字符串。爲了防止該行爲,在字典中鍵不是字符串的地方加入一個額外的項,即上面postfix=["Batch", dict(value=0)]中的value=0

額外的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(TqdmExtraFormat, self).format_dict
#d["total"]表示總迭代數,d["n"]表示當前爲第幾輪迭代 print(d[
"elapsed"], d["total"], d["n"]) 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(10), ascii=" .oO0", bar_format="{total_time}: {percentage:.0f}%|{bar}{r_bar}"): sleep(0.25) print(i)

返回:

00:00 in total: 0%|          | 0/10 [00:00<?, ?it/s]
0 10 0
00:02 in total: 10%|0         | 1/10 [00:00<00:02,  3.92it/s]
0
0.2551310062408447 10 1
00:02 in total: 20%|00        | 2/10 [00:00<00:02,  3.92it/s]
1
0.5111739635467529 10 2
00:02 in total: 30%|000       | 3/10 [00:00<00:01,  3.91it/s]
2
0.7674551010131836 10 3
00:02 in total: 40%|0000      | 4/10 [00:01<00:01,  3.92it/s]
3
1.0219080448150635 10 4
00:02 in total: 50%|00000     | 5/10 [00:01<00:01,  3.93it/s]
4
1.2738640308380127 10 5
00:02 in total: 60%|000000    | 6/10 [00:01<00:01,  3.94it/s]
5
1.525794267654419 10 6
00:02 in total: 70%|0000000   | 7/10 [00:01<00:00,  3.94it/s]
6
1.7809131145477295 10 7
00:02 in total: 80%|00000000  | 8/10 [00:02<00:00,  3.94it/s]
7
2.035114049911499 10 8
00:02 in total: 90%|000000000 | 9/10 [00:02<00:00,  3.93it/s]
8
2.2901201248168945 10 9
00:02 in total: 100%|0000000000| 10/10 [00:02<00:00,  3.93it/s]
9
2.543692111968994 10 10
2.544473886489868 10 10

參數ascii=" .oO0"指定使用0來填補進度條

參數bar_format="{total_time}: {percentage:.0f}%|{bar}{r_bar}"定義的值total_time即覆寫format_dict中定義的total_time值,即輸出的00:00 in total{percentage:.0f}%即表示進度的百分比,小數位值不顯示,設爲0;因此l_bar = {total_time}: {percentage:.0f}%|,{bar}{r_bar}沒有定義,即表示使用默認定義

 

注意{bar}還支持格式說明符[width][type]

  • width:
  1. 未指定(默認值):自動填充ncols
  2. 設置的是整數且int >= 0: 即覆蓋ncols邏輯的固定寬度
  3. 設置的是整數且int < 0: 則使用默認值減去該值
  • type:
  1. a : ascii (覆寫即等價於ascii=True)
  2. u : unicode(覆寫 ascii=False)
  3. b : blank(覆寫 ascii=" ")

這意味着可使用如下方法建立具備右對齊文本的固定欄:bar_format="{l_bar}{bar:10}|{bar:-10b}right-justified"

 

Nested progress bars

tqdm支持嵌套的進度條。這裏有一個例子:

from tqdm import trange
from time import sleep

for i in trange(4, desc='1st loop'):
    for j in trange(5, desc='2nd loop'):
        for k in trange(20, desc='3nd loop', leave=False):
            sleep(0.01)

返回:

1st loop:   0%|          | 0/4 [00:00<?, ?it/s]
2nd loop:   0%|          | 0/5 [00:00<?, ?it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 90.89it/s]

3nd loop:  95%|█████████▌| 19/20 [00:00<00:00, 90.62it/s]

                                                         
2nd loop:  20%|██        | 1/5 [00:00<00:00,  4.39it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  45%|████▌     | 9/20 [00:00<00:00, 86.21it/s]

3nd loop:  90%|█████████ | 18/20 [00:00<00:00, 85.41it/s]

                                                         
2nd loop:  40%|████      | 2/5 [00:00<00:00,  4.29it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 95.65it/s]

3nd loop:  95%|█████████▌| 19/20 [00:00<00:00, 93.32it/s]

                                                         
2nd loop:  60%|██████    | 3/5 [00:00<00:00,  4.31it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 92.64it/s]

3nd loop:  95%|█████████▌| 19/20 [00:00<00:00, 91.18it/s]

                                                         
2nd loop:  80%|████████  | 4/5 [00:00<00:00,  4.32it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 94.50it/s]

3nd loop:  95%|█████████▌| 19/20 [00:00<00:00, 91.41it/s]

                                                         
2nd loop: 100%|██████████| 5/5 [00:01<00:00,  4.27it/s]
1st loop:  25%|██▌       | 1/4 [00:01<00:03,  1.17s/it]
2nd loop:   0%|          | 0/5 [00:00<?, ?it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 90.59it/s]

3nd loop:  95%|█████████▌| 19/20 [00:00<00:00, 89.93it/s]

                                                         
2nd loop:  20%|██        | 1/5 [00:00<00:00,  4.33it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 91.40it/s]

3nd loop:  95%|█████████▌| 19/20 [00:00<00:00, 90.54it/s]

                                                         
2nd loop:  40%|████      | 2/5 [00:00<00:00,  4.32it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 93.82it/s]

3nd loop:  95%|█████████▌| 19/20 [00:00<00:00, 91.93it/s]

                                                         
2nd loop:  60%|██████    | 3/5 [00:00<00:00,  4.34it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 96.33it/s]

3nd loop: 100%|██████████| 20/20 [00:00<00:00, 94.51it/s]

                                                         
2nd loop:  80%|████████  | 4/5 [00:00<00:00,  4.37it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 93.01it/s]

3nd loop: 100%|██████████| 20/20 [00:00<00:00, 92.52it/s]

                                                         
2nd loop: 100%|██████████| 5/5 [00:01<00:00,  4.36it/s]
1st loop:  50%|█████     | 2/4 [00:02<00:02,  1.17s/it]
2nd loop:   0%|          | 0/5 [00:00<?, ?it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 92.09it/s]

3nd loop:  95%|█████████▌| 19/20 [00:00<00:00, 90.62it/s]

                                                         
2nd loop:  20%|██        | 1/5 [00:00<00:00,  4.33it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 90.28it/s]

3nd loop:  95%|█████████▌| 19/20 [00:00<00:00, 89.40it/s]

                                                         
2nd loop:  40%|████      | 2/5 [00:00<00:00,  4.31it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 94.83it/s]

3nd loop:  95%|█████████▌| 19/20 [00:00<00:00, 92.97it/s]

                                                         
2nd loop:  60%|██████    | 3/5 [00:00<00:00,  4.32it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 90.53it/s]

3nd loop:  95%|█████████▌| 19/20 [00:00<00:00, 90.02it/s]

                                                         
2nd loop:  80%|████████  | 4/5 [00:00<00:00,  4.33it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 91.51it/s]

3nd loop:  95%|█████████▌| 19/20 [00:00<00:00, 89.57it/s]

                                                         
2nd loop: 100%|██████████| 5/5 [00:01<00:00,  4.29it/s]
1st loop:  75%|███████▌  | 3/4 [00:03<00:01,  1.17s/it]
2nd loop:   0%|          | 0/5 [00:00<?, ?it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 94.66it/s]

3nd loop:  95%|█████████▌| 19/20 [00:00<00:00, 92.52it/s]

                                                         
2nd loop:  20%|██        | 1/5 [00:00<00:00,  4.41it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  45%|████▌     | 9/20 [00:00<00:00, 88.28it/s]

3nd loop:  95%|█████████▌| 19/20 [00:00<00:00, 88.91it/s]

                                                         
2nd loop:  40%|████      | 2/5 [00:00<00:00,  4.36it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  45%|████▌     | 9/20 [00:00<00:00, 86.31it/s]

3nd loop:  90%|█████████ | 18/20 [00:00<00:00, 86.96it/s]

                                                         
2nd loop:  60%|██████    | 3/5 [00:00<00:00,  4.31it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  45%|████▌     | 9/20 [00:00<00:00, 89.50it/s]

3nd loop:  90%|█████████ | 18/20 [00:00<00:00, 87.95it/s]

                                                         
2nd loop:  80%|████████  | 4/5 [00:00<00:00,  4.27it/s]

3nd loop:   0%|          | 0/20 [00:00<?, ?it/s]

3nd loop:  50%|█████     | 10/20 [00:00<00:00, 92.30it/s]

3nd loop: 100%|██████████| 20/20 [00:00<00:00, 91.61it/s]

                                                         
2nd loop: 100%|██████████| 5/5 [00:01<00:00,  4.26it/s]
1st loop: 100%|██████████| 4/4 [00:04<00:00,  1.17s/it]
View Code

參數desc='3nd loop'指定輸出的l_bar的內容,即前綴

在Windows上,若是能夠的話,colorama將用於保持嵌套條在各自的行上。
對於手動控制定位(例如多線程使用),能夠指定位置=n,其中最外層的欄位n=0,下一欄位n=1,以此類推:

from time import sleep
from tqdm import trange, tqdm
from multiprocessing import Pool, freeze_support, RLock

L = list(range(3))

def progresser(n):
    interval = 0.001 / (n + 2)
    total = 5000
    # {:<04.2}表示左對齊,數字總共4位,其中小數兩位
    text = "#{}, est. {:<04.2}s".format(n, interval * total)
    for i in trange(total, desc=text, position=n):
        sleep(interval)

if __name__ == '__main__':
    freeze_support()  # for Windows support
    p = Pool(len(L), # 同時開啓3個進程
             # again, for Windows support
             initializer=tqdm.set_lock, initargs=(RLock(),))
    p.map(progresser, L)
    print("\n" * (len(L) - 2)) #換行

返回:

#0, est. 2.50s:   0%|          | 0/5000 [00:00<?, ?it/s]
#1, est. 1.70s:   0%|          | 0/5000 [00:00<?, ?it/s]

#0, est. 2.50s:   4%|▎         | 175/5000 [00:00<00:02, 1743.72it/s]
#1, est. 1.70s:   5%|▌         | 258/5000 [00:00<00:01, 2577.38it/s]

#0, est. 2.50s:   7%|▋         | 346/5000 [00:00<00:02, 1731.96it/s]
#1, est. 1.70s:  10%|█         | 500/5000 [00:00<00:01, 2525.19it/s]

#0, est. 2.50s:  10%|█         | 515/5000 [00:00<00:02, 1717.89it/s]
#1, est. 1.70s:  15%|█▍        | 729/5000 [00:00<00:01, 2447.84it/s]

#0, est. 2.50s:  14%|█▎        | 685/5000 [00:00<00:02, 1712.16it/s]
#1, est. 1.70s:  19%|█▉        | 959/5000 [00:00<00:01, 2401.48it/s]

#0, est. 2.50s:  17%|█▋        | 855/5000 [00:00<00:02, 1707.39it/s]]
#1, est. 1.70s:  24%|██▍       | 1200/5000 [00:00<00:01, 2403.36it/s]

#0, est. 2.50s:  21%|██        | 1026/5000 [00:00<00:02, 1706.94it/s]
#1, est. 1.70s:  29%|██▊       | 1435/5000 [00:00<00:01, 2385.71it/s]

#0, est. 2.50s:  24%|██▍       | 1198/5000 [00:00<00:02, 1709.67it/s]
#1, est. 1.70s:  34%|███▎      | 1675/5000 [00:00<00:01, 2389.13it/s]

#0, est. 2.50s:  27%|██▋       | 1369/5000 [00:00<00:02, 1707.61it/s]
#1, est. 1.70s:  38%|███▊      | 1914/5000 [00:00<00:01, 2387.64it/s]

#0, est. 2.50s:  31%|███       | 1541/5000 [00:00<00:02, 1709.89it/s]
#1, est. 1.70s:  43%|████▎     | 2153/5000 [00:00<00:01, 2388.28it/s]

#0, est. 2.50s:  34%|███▍      | 1712/5000 [00:01<00:01, 1708.18it/s]
#1, est. 1.70s:  48%|████▊     | 2392/5000 [00:01<00:01, 2387.33it/s]

#0, est. 2.50s:  38%|███▊      | 1882/5000 [00:01<00:01, 1704.82it/s]
#1, est. 1.70s:  53%|█████▎    | 2632/5000 [00:01<00:00, 2388.09it/s]

#0, est. 2.50s:  41%|████      | 2052/5000 [00:01<00:01, 1701.67it/s]
#1, est. 1.70s:  57%|█████▋    | 2867/5000 [00:01<00:00, 2376.26it/s]

#0, est. 2.50s:  44%|████▍     | 2224/5000 [00:01<00:01, 1704.14it/s]
#1, est. 1.70s:  62%|██████▏   | 3106/5000 [00:01<00:00, 2379.52it/s]

#0, est. 2.50s:  48%|████▊     | 2395/5000 [00:01<00:01, 1702.96it/s]
#1, est. 1.70s:  67%|██████▋   | 3342/5000 [00:01<00:00, 2364.88it/s]

#0, est. 2.50s:  51%|█████▏    | 2566/5000 [00:01<00:01, 1703.43it/s]
#1, est. 1.70s:  72%|███████▏  | 3579/5000 [00:01<00:00, 2365.95it/s]

#0, est. 2.50s:  55%|█████▍    | 2736/5000 [00:01<00:01, 1702.05it/s]
#1, est. 1.70s:  76%|███████▋  | 3817/5000 [00:01<00:00, 2368.33it/s]

#2, est. 1.20s: 100%|██████████| 5000/5000 [00:01<00:00, 3076.41it/s]
#0, est. 2.50s:  58%|█████▊    | 2906/5000 [00:01<00:01, 1695.95it/s]
#0, est. 2.50s:  62%|██████▏   | 3076/5000 [00:01<00:01, 1688.59it/s]
#0, est. 2.50s:  65%|██████▍   | 3245/5000 [00:01<00:01, 1687.35it/s]
#0, est. 2.50s:  68%|██████▊   | 3414/5000 [00:02<00:00, 1680.56it/s]
#0, est. 2.50s:  72%|███████▏  | 3582/5000 [00:02<00:00, 1674.84it/s]
#1, est. 1.70s: 100%|██████████| 5000/5000 [00:02<00:00, 2354.49it/s]
#0, est. 2.50s: 100%|██████████| 5000/5000 [00:02<00:00, 1672.28it/s]
View Code

 

Hooks and callbacks

tqdm能夠很容易地支持回調/鉤子和手動更新。下面是urllib的一個例子:

urllib.urlretrieve documentation

若是存在,鉤子函數將在網絡鏈接創建時調用一次,以後在讀取每一個塊以後調用一次。

鉤子將傳遞三個參數:到目前爲止傳輸的塊數、塊大小(以字節爲單位)和文件的總大小。

報錯:

module 'urllib' has no attribute 'urlretrieve'

緣由是python2 與python3的urllib不一樣在與python3要加上.request,更改後爲:

import urllib, os
from tqdm import tqdm

class TqdmUpTo(tqdm):
    """Provides `update_to(n)` which uses `tqdm.update(delta_n)`."""
    def update_to(self, b=1, bsize=1, tsize=None):
        """
        b  : int, optional
            Number of blocks transferred so far [default: 1].
        bsize  : int, optional
            Size of each block (in tqdm units) [default: 1].
        tsize  : int, optional
            Total size (in tqdm units). If [default: None] remains unchanged.
        """
        if tsize is not None:
            self.total = tsize
        self.update(b * bsize - self.n)  # will also set self.n = b * bsize

eg_link = "https://caspersci.uk.to/matryoshka.zip"
with TqdmUpTo(unit='B', unit_scale=True, miniters=1,
              desc=eg_link.split('/')[-1]) as t:  # all optional kwargs
    urllib.request.urlretrieve(eg_link, filename=os.devnull,
                       reporthook=t.update_to, data=None)

最終爲:

matryoshka.zip: 262kB [00:03, 77.4kB/s]  

靈感來自 twine#242。對examples/tqdm_wget.py進行函數替代。
當迭代速度存在較大差別時,建議使用miniter =1(例如,經過不完整的鏈接下載文件)。

 

Pandas Integration

受廣大要求求,咱們增長了對panda的支持——下面是DataFrame.progress_apply和DataFrameGroupBy.progress_apply的一個例子:

出錯:

ModuleNotFoundError: No module named 'pandas'

解決:

(deeplearning) userdeMacBook-Pro:~ user$ conda install -n deeplearning pandas

更改後例子:

import pandas as pd
import numpy as np
from tqdm import tqdm

df = pd.DataFrame(np.random.randint(0, 100, (100000, 6)))

# Register `pandas.progress_apply` and `pandas.Series.map_apply` with `tqdm`
# (can use `tqdm_gui`, `tqdm_notebook`, optional kwargs, etc.)
tqdm.pandas(desc="my bar!")

# Now you can use `progress_apply` instead of `apply`
# and `progress_map` instead of `map`
df.progress_apply(lambda x: x**2)
# can also groupby:
# df.groupby(0).progress_apply(lambda x: x**2)

返回:

/anaconda3/envs/deeplearning/bin/src/tqdm/tqdm/_tqdm.py:634: FutureWarning: The Panel class is removed from pandas. Accessing it from the top-level namespace will also be removed in the next version
  from pandas import Panel
my bar!: 100%|██████████| 6/6 [00:00<00:00, 265.34it/s]

數據大小爲(100000, 6),從[0,100)中隨機取值對其賦初值,而後求平方:

若是您對它的工做原理(以及如何爲您本身的回調修改它)感興趣,請參閱examples文件夾或導入模塊並運行help()。

 

IPython/Jupyter Integration

IPython/Jupyter經過tqdm_notebook子模塊支持:

出錯:

IntProgress not found. Please update jupyter and ipywidgets.

解決參考https://ipywidgets.readthedocs.io/en/stable/user_install.html

個人操做爲:

(deeplearning) userdeMacBook-Pro:~ user$ conda install -n deeplearning ipywidgets

例子:

from tqdm import tnrange, tqdm_notebook
from time import sleep

for i in tnrange(3, desc='1st loop'):
    for j in tqdm_notebook(range(100), desc='2nd loop'):
        sleep(0.01)

返回:

 

除了tqdm特性外,子模塊還提供了一個本機Jupyter小部件(兼容IPython v1-v4和Jupyter),徹底工做的嵌套條和顏色提示(藍色:normal、綠色:completed、紅色:error/interrupt、淡藍色:no ETA);以下顯示

from tqdm import tnrange, tqdm_notebook
from time import sleep

for i in tqdm_notebook(range(3), desc='1st loop'):
    for j in tqdm_notebook(range(100), desc='2nd loop'):
        sleep(0.01)

過程爲:

 

 最終爲:

若是添加參數leave=True:

from tqdm import tnrange, tqdm_notebook
from time import sleep

for i in tqdm_notebook(range(3), desc='1st loop'):
    for j in tqdm_notebook(range(100), desc='2nd loop', leave=False):
        sleep(0.01)

則最後只會留下外層嵌套的結果:

 

若是中間點擊中止按鈕,則標明紅色:

 

 tqdm也能夠經過使用autonotebook子模塊自動選擇控制檯或筆記本版本:

from tqdm.autonotebook import tqdm
tqdm.pandas()

返回:

/anaconda3/envs/deeplearning/bin/src/tqdm/tqdm/autonotebook/__init__.py:18: TqdmExperimentalWarning: Using `tqdm.autonotebook.tqdm` in notebook mode. Use `tqdm.tqdm` instead to force console mode (e.g. in jupyter console)
  " (e.g. in jupyter console)", TqdmExperimentalWarning)

注意,若是運行在一個筆記本上,這將發出tqdmexperimental警告,由於其不可能區分jupyter notebook和jupyter console。使用auto而不是autonotebook來抑制這個警告。

 

Custom Integration

能夠繼承tqdm來建立自定義回調(如上面的TqdmUpTo示例)或自定義前端(例如GUIs,如筆記本或繪圖包)。在後一種狀況下要作的有:

  • 在def __init__()中調用super().__init__(..., gui=True)來要禁用終端status_printer建立。
  • 重定義close(), clear(), display()三個函數

考慮重載display()來使用self.frontend(** .format_dict)而不是self.sp(repr(self))。

 

Dynamic Monitor/Meter

你能夠用tqdm做爲一個非單調增加的meter。這多是由於n減小(例如CPU使用監視器)或total更改。
一個例子是遞歸搜索文件。total是目前找到的對象數量,n是文件(而不是文件夾)的對象數量:

from tqdm import tqdm
import os.path

def find_files_recursively(path, show_progress=True):
    files = []
    # total=1 assumes `path` is a file
    t = tqdm(total=1, unit="file", disable=not show_progress)
    if not os.path.exists(path):
        raise IOError("Cannot find:" + path)

    def append_found_file(f):
        files.append(f)
        t.update()

    def list_found_dir(path):
        """returns os.listdir(path) assuming os.path.isdir(path)"""
        listing = os.listdir(path)
        # subtract 1 since a "file" we found was actually this directory
        t.total += len(listing) - 1
        # fancy way to give info without forcing a refresh
        t.set_postfix(dir=path[-10:], refresh=False)
        t.update(0)  # may trigger a refresh
        return listing

    def recursively_search(path):
        if os.path.isdir(path):
            for f in list_found_dir(path):
                recursively_search(os.path.join(path, f))
        else:
            append_found_file(path)

    recursively_search(path)
    t.set_postfix(dir=path)
    t.close()
    return files

使用update(0)是讓tqdm決定什麼時候觸發顯示刷新以免控制檯垃圾信息的一種簡便方法。

 

Writing messages

這是一項正在進行的工做(見#737)。
因爲tqdm使用簡單的打印機制來顯示進度條,因此在打開進度條時,不該該在終端中使用print()編寫任何消息。
爲了在終端中寫入消息而不與tqdm bar顯示發生衝突,提供了.write()方法:

from tqdm import tqdm, trange
from time import sleep

bar = trange(10)
for i in bar:
    # Print using tqdm class method .write()
    sleep(0.1)
    if not (i % 3):
        tqdm.write("Done task %i" % i)
    # Can also use bar.write()

返回:

 20%|██        | 2/10 [00:00<00:00,  9.48it/s]
Done task 0
 50%|█████     | 5/10 [00:00<00:00,  9.53it/s]
Done task 3
 80%|████████  | 8/10 [00:00<00:00,  9.50it/s]
Done task 6
100%|██████████| 10/10 [00:01<00:00,  9.56it/s]
Done task 9

默認狀況下,這將打印到標準輸出sys.stdout。可是您可使用file參數指定任何相似文件的對象。例如,這能夠用於將寫入的消息重定向到日誌文件或類。

 

Redirecting writing

若是使用一個能夠將消息打印到控制檯的庫,那麼用tqdm.write()替換print()來編輯庫多是不可取的。在這種狀況下,重定向sys.stdout到tqdm.write()是一個選擇。
重定向sys.stdout,建立一個相似於文件的類,該類將向tqdm.write()寫入任何輸入字符串,並提供參數file=sys.stdout, dynamic_ncols = True。
一個可重用的規範示例以下:

from time import sleep
import contextlib
import sys
from tqdm import tqdm

class DummyTqdmFile(object):
    """Dummy file-like that will write to tqdm"""
    file = None
    def __init__(self, file):
        self.file = file

    def write(self, x):
        # Avoid print() second call (useless \n)
        if len(x.rstrip()) > 0:
            tqdm.write(x, file=self.file)

    def flush(self):
        return getattr(self.file, "flush", lambda: None)()

@contextlib.contextmanager
def std_out_err_redirect_tqdm():
    orig_out_err = sys.stdout, sys.stderr
    try:
        sys.stdout, sys.stderr = map(DummyTqdmFile, orig_out_err)
        yield orig_out_err[0]
    # Relay exceptions
    except Exception as exc:
        raise exc
    # Always restore sys.stdout/err if necessary
    finally:
        sys.stdout, sys.stderr = orig_out_err

def some_fun(i):
    print("Fee, fi, fo,".split()[i])

# Redirect stdout to tqdm.write() (don't forget the `as save_stdout`)
with std_out_err_redirect_tqdm() as orig_stdout:
    # tqdm needs the original stdout
    # and dynamic_ncols=True to autodetect console width
    for i in tqdm(range(3), file=orig_stdout, dynamic_ncols=True):
        sleep(.5)
        some_fun(i)

# After the `with`, printing is restored
print("Done!")

返回:

Fee,                                 
fi,                                          
fo,                                          
100%|██████████| 3/3 [00:01<00:00,  1.97it/s]
Done!

 

Monitoring thread, intervals and miniters

tqdm實現了一些技巧來提升效率和減小開銷。

  • 避免沒必要要的頻繁刷新:mininterval定義每次刷新之間要等待多長時間。tqdm老是在後臺更新,但它只顯示每分鐘一次。
  • 減小檢查系統時鐘/時間的次數。
  • mininterval比miniter更易於配置。一個聰明的調整系統dynamic_miniter將自動調整miniter到適合時間mininterval的迭代量。本質上,tqdm將在沒有實際檢查時間的狀況下檢查是否須要打印。這種行爲仍然能夠經過手動設置miniter來繞過。

然而,考慮一個結合了快速和緩慢迭代的案例。通過幾回快速迭代以後,dynamic_miniter將把miniter設置爲一個很大的數字。當迭代速率隨後減慢時,miniter將保持較大的值,從而下降顯示更新頻率。爲了解決這個問題:

  • maxinterval定義顯示刷新之間的最大時間間隔。併發監視線程檢查過時的更新,並在必要時強制執行更新。

監視線程不該該有明顯的開銷,而且默認狀況下保證至少每10秒更新一次。能夠經過設置任何tqdm實例的monitor_interval(即t = tqdm.tqdm(…); t.monitor_interval = 2)直接更改此值。經過設置tqdm.tqdm.monitor_interval = 0能夠在實例化任何tqdm bar以前在應用程序範圍內禁用監視器線程。

相關文章
相關標籤/搜索