闪米特语词根 q-d-m 在阿拉姆语、希伯来语和阿拉伯语中通常与前进或取得进步有关。阿拉伯语单词 taqaddum (تقدّم) 意为“进步”。进步很重要。正如每一部感觉良好的电影都会告诉你的那样,旅程与目的地一样重要。
大多数程序都有一个明确的目标,一个期望的最终状态。有时,计算最终状态可能需要很长时间。虽然计算机不在乎,没有感情,但人们却在乎。人类不喜欢坐着等待而没有任何可见的进度迹象。怀疑悄然而生。程序崩溃了吗?磁盘在猛烈地抖动吗?操作系统是否将其所有计算资源都分配给了其他任务?
就像正义一样,进步必须被看到,而不仅仅是被完成。tqdm Python 库有助于使进度显而易见。
tqdm 模块与控制台配合使用,但它也特别支持我最喜欢的环境之一:Jupyter。要在 Jupyter 中使用 tqdm,您需要导入 notebook
子模块并安装 ipywidgets。notebook
子模块与 tqdm 接口兼容。
这意味着您可以进行一些导入时的恶作剧,以导入正确的模块,同时保持 tqdm 的用法不变。诀窍是检查 __main__
模块是否具有全局变量 get_ipython
。虽然这是一种启发式方法,但它相当准确
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
少量改进就可以使您非常接近。例如,您可以计算 2 的平方根
guess = 1
target = 2
for i in tqdm.trange(10):
guess = improve_guess(guess, target)

(Moshe Zadke,CC BY-SA 4.0)
它精确到小数点后 10 位!
round(2 - guess*guess, 10)
0.0
一个稍微复杂的例子是,当元素的数量已知,并且处理每个元素花费的时间相似时。例如,您可以计算一些数字的乘积。为此,您需要一些随机数
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 最简单的方法是包装一个 Python 可迭代对象。这些值将是相同的,但 tqdm 也会显示一个进度条
result = 1
for num in tqdm.tqdm(numbers):
result *= num
result
2.4081854901728303

(Moshe Zadke,CC BY-SA 4.0)
然而,并非所有事情都是可预测的。最不可预测的事情之一是网络速度。当您下载一个大文件时,衡量进度的唯一方法是显式检查已下载了多少
url = "https://pythonlang.cn/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))

(Moshe Zadke,CC BY-SA 4.0)
有时,嵌套进度条是有意义的。例如,如果您正在下载一个目录,您将需要一个跟踪文件的进度条和一个每个文件的进度条。
这是一个示例(但实际上没有下载目录)
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)

(Moshe Zadke,CC BY-SA 4.0)
因此,如果您的程序需要一段时间才能显示最终结果,请避免让用户感到沮丧:显示它正在取得的进度!
评论已关闭。