进度条tqdm
tqdm(读音:taqadum,阿拉伯语“进步”的意思)是一个快速、可扩展的 Python 进度条库。它可以在长循环中添加一个智能进度提示信息,用户只需要封装任意的迭代器 tqdm(iterable) 即可。
1. 安装
在终端或命令行中执行:
pip install tqdm
2. 基础用法
2.1 自动控制 (最常用)
这是最简单的用法,直接用 tqdm() 包裹你的迭代对象(如 list, range 等)。
from tqdm import tqdm
import time
# 包裹 range
for i in tqdm(range(100)):
time.sleep(0.01)
# 包裹 list
my_list = ["a", "b", "c", "d"]
for char in tqdm(my_list):
time.sleep(0.2)
2.2 使用 trange
trange(i) 是 tqdm(range(i)) 的特化版本,写法更简洁。
from tqdm import trange
import time
for i in trange(100):
time.sleep(0.01)
3. 进阶参数配置
tqdm 提供了丰富的参数来定制进度条的外观和信息。
常用参数说明:
-
desc: 进度条的前缀描述(字符串)。 -
total: 预期的迭代总次数。如果包裹的是len()已知的对象,会自动识别;如果是生成器,建议手动指定,否则只显示处理数量。 -
ncols: 进度条的宽度(字符数)。 -
unit: 单位名称(默认是it),例如设置为img,KB等。 -
postfix: 字典形式的后缀信息,实时显示在进度条末尾(如 loss, accuracy)。
示例代码:
from tqdm import tqdm
import time
# 假设处理一批图片
pbar = tqdm(range(100), desc="Processing Images", unit="img", ncols=100)
for i in pbar:
time.sleep(0.05)
# 实时更新后缀信息,例如当前的损失值
current_loss = 1 / (i + 1)
pbar.set_postfix({"loss": f"{current_loss:.4f}", "status": "ok"})
4. 手动控制更新
当无法直接使用迭代器(例如在 while 循环中,或通过回调函数下载文件)时,可以使用 with 语句手动更新进度条。
from tqdm import tqdm
import time
# 手动指定总数 total=100
with tqdm(total=100, desc="Manual Update") as pbar:
for i in range(10):
time.sleep(0.1)
# 每次更新 10 个单位
pbar.update(10)
5. 高级场景集成
5.1 Pandas 集成 (progress_apply)
这是数据分析中最实用的功能之一。tqdm 可以通过 progress_apply 替代 Pandas 的 apply 方法,显示处理进度。
import pandas as pd
import numpy as np
from tqdm import tqdm
# 1. 初始化 tqdm 的 pandas 适配器
tqdm.pandas(desc="Processing DataFrame")
# 创建一个较大的 DataFrame
df = pd.DataFrame(np.random.randint(0, 100, (100000, 6)))
# 2. 使用 progress_apply 替代 apply
# 假设我们要计算每行的平方和
result = df.progress_apply(lambda x: x**2, axis=1)
5.2 Jupyter Notebook 专用 (tqdm.notebook)
在 Jupyter Notebook / Lab 中,标准的文本进度条可能显示错乱或不够美观。建议使用 tqdm.notebook 模块,它会渲染出原生的 HTML 进度条(包含颜色提示,红色代表失败/中断)。
# 注意导入路径
from tqdm.notebook import tqdm, trange
import time
for i in tqdm(range(100), desc="Jupyter Progress"):
time.sleep(0.05)
5.3 多层嵌套循环
tqdm 会自动处理嵌套循环的缩进。通过设置 leave=False,可以让内层循环在完成后清除进度条,保持输出整洁。
from tqdm import trange
from time import sleep
for i in trange(3, desc='Outer Loop'):
# leave=False 表示内层跑完后清除该行,避免刷屏
for j in trange(5, desc='Inner Loop', leave=False):
sleep(0.1)
5.4 命令行管道模式
tqdm 也可以在 Shell 中作为管道使用。
# 示例:显示压缩文件的进度
# 将当前目录下的文件打包,通过管道传给 tqdm 统计进度(基于字节),最后输出到文件
tar -cf - . | tqdm --bytes --total $(du -sb . | cut -f1) > backup.tar
6. 常见问题与技巧
- 性能开销:
tqdm 的开销非常低(纳秒级),对于耗时操作(如网络请求、文件IO、模型训练)几乎可以忽略不计。如果循环体极其快速(例如纯简单的加法),进度条的刷新可能会成为瓶颈,此时可以设置mininterval参数(默认为 0.1秒),降低刷新频率。 - 生成器长度未知:如果处理的是生成器(generator),
tqdm 无法预知total,此时进度条只会显示已处理的数量和速度,不会显示剩余时间和百分比。解决方法是尽可能传入total参数。
def my_gen():
for i in range(100):
yield i
# 显式告知总数
for i in tqdm(my_gen(), total=100):
pass
- 多进程/多线程:在多进程环境中使用
tqdm 需要注意锁的问题,通常建议使用tqdm.contrib.concurrent 中的process_map 或thread_map来简化操作。
from tqdm.contrib.concurrent import process_map
import time
def _foo(my_number):
time.sleep(1)
return my_number**2
# 自动并行处理并显示进度条
r = process_map(_foo, range(10), max_workers=2)