1.7 萬 Star!一個簡單實用的 Python 進度條庫

【導讀】:有的 Python 程序較大,執行須要花費較長的時間,有的用戶在「盲目」地等待運行結果,但又不能明確知道程序進展到什麼程度的時候,頗有可能因心情急躁而終止程序。python

本文介紹的這個有着 1.7 萬 Star 的開源庫,就能解決這個煩惱。git

https://github.com/tqdm/tqdmgithub

一、Tqdm 簡介

使用 Python Tqdm 進度條庫,可讓 python 程序執行進度可視化。算法

示例

在阿拉姆語(Aramaic)、希伯來語(Hebrew)、和阿拉伯語(Arabic)中,閃米特語(Semitic)詞根 q-d-m一般與 前進取得進步的意思掛鉤。例如,阿拉伯語單詞 taqaddum (تقدّم) 的意思是「進步」。進步是重要的,就像每一部使人愉悅的電影都會向你傳達一個哲理——旅途和目的地同樣重要。

大多數程序都有一個明確目標,那就是程序運行的最終(結束)狀態,成功仍是失敗!可是每每有時候程序的運行可能須要很長時間。儘管計算機沒有情感,不在意程序執行時間的長短,但是人們是在意的。網絡

隨着時間推移,程序運行人員或用戶的疑問會不斷蔓延(程序崩潰了嗎?磁盤跳動了嗎?操做系統是否將全部計算資源分配給了其餘任務?)當程序運行過程當中長時間沒有任何的進展跡象時,程序運行人員可能會疑慮、煩躁,不肯意繼續等待下去。而本文講的 tqdm 庫便有助於明確顯示程序的執行進度。dom

二、使用方法

tqdm 庫模塊能夠在命令控制檯一塊兒使用,可是也支持我最喜歡的開發環境之一的 Jupyter notebook。若是想在 Jupyter notebook 中使用 tqdm,notebook 模塊與 tqdm 接口兼容,須要導入 notebook 子模塊並安裝ipywidgeturl

這就意味着你能夠在導入 tqdm 庫操做以前作一下條件判斷,這個判斷方法是檢查_main_模塊中是否有get_ipython全局變量。雖然上面這個判斷導庫方法是一個啓發式的,但它是一個至關準確的方法:spa

import sys
if hasattr(sys.modules["__main__"],"get_ipython"):
    from tqdm import notebook as tqdm
else:
    import tqdm

舉個最簡單的狀況來助於理解一下,某程序須要執行必定數量的迭代(迭代次數預先可知),可是這些迭代中的每一次迭代花費大約相同的時間。例如,一個能夠計算任意數字平方根的算法,算法是從1開始,而後計算一個進度估計。操作系統

def improve_guess(rt, n):
    return (rt + n/rt) / 2

對以上代碼的少量改進可讓你更容易理解:3d

guess = 1
target = 2
for i in tqdm.trange(10):
    guess = improve_guess(guess, target)

精確到小數點後十位:

round(2 - guess*guess, 10)
0.0

再舉一個稍微複雜的tqdm例子,當處理的元素數量已知且計算每一個元素的時間類似。例如,計算一些隨機數字的伺機:

import random
numbers = [random.uniform(0, 2.8) for i in range(100)]
numbers[:5]
[2.6575636572230916,
0.1286674965830302,
1.0634250104041332,
1.1760969844376505,
0.45192978568125486]

數值元素有了,接下來使用tqdm顯示進度條,使用tqdm最簡單的方法是封裝Python中可迭代的對象。

result = 1
for num in tqdm.tqdm(numbers):
    result *= num
result
2.4081854901728303

可是,不是全部的事情都是可預測的,其中不可預測的事情之一是網絡速度。下載大文件時,衡量進度的惟一的方法是顯示已經下載了多少文件:

url = "https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz"
import httpx
with httpx.stream("GET", url) as response:
    total = int(response.headers["Content-Length"])
    with tqdm.tqdm(total=total) as progress:
        for chunk in response.iter_bytes():
            progress.update(len(chunk))

有時,「嵌套」進度條是有意義的。例如,若是正在下載一個目錄,則須要一個跟蹤文件的進度條和每一個文件的進度條。
下面是一個示例(但沒有實際下載目錄):

files = [f"vid-{i}.mp4" for i in range(4)]
for fname in tqdm.tqdm(files, desc="files"):
    total = random.randrange(10**9, 2 * 10**9)
    with tqdm.tqdm(total=total, desc=fname) as progress:
        current = 0
        while current < total:
            chunk_size = min(random.randrange(10**3, 10**5), total - current)
            current += chunk_size
            if random.uniform(0, 1) < 0.01:
                time.sleep(0.1)
            progress.update(chunk_size)

所以,若是你的程序須要一段時間才能顯示最終結果,爲了不用戶感到沮喪:顯示它的進度狀況!

開源前哨 平常分享熱門、有趣和實用的開源項目。參與維護 10萬+ Star 的開源技術資源庫,包括:Python、Java、C/C++、Go、JS、CSS、Node.js、PHP、.NET 等。
相關文章
相關標籤/搜索