进度条tqdm

3 阅读1分钟

进度条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. 常见问题与技巧

  1. 性能开销​:tqdm​ 的开销非常低(纳秒级),对于耗时操作(如网络请求、文件IO、模型训练)几乎可以忽略不计。如果循环体极其快速(例如纯简单的加法),进度条的刷新可能会成为瓶颈,此时可以设置 mininterval 参数(默认为 0.1秒),降低刷新频率。
  2. 生成器长度未知​:如果处理的是生成器(generator),tqdm​ 无法预知 total​,此时进度条只会显示已处理的数量和速度,不会显示剩余时间和百分比。解决方法是尽可能传入 total 参数。
def my_gen():
    for i in range(100):
        yield i

# 显式告知总数
for i in tqdm(my_gen(), total=100):
    pass
  1. 多进程/多线程​:在多进程环境中使用 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)