tqdm(阿拉伯语"进步"的缩写)是一个快速、可扩展的 Python 进度条库,可以在循环执行耗时操作时显示进度信息。

安装

pip install tqdm

基本用法

1. 包装可迭代对象

from tqdm import tqdm
import time

# 基本用法:包装任何可迭代对象
for i in tqdm(range(100)):
    time.sleep(0.01)  # 模拟耗时操作

2. 手动更新进度条

from tqdm import tqdm
import time

# 手动控制进度条
pbar = tqdm(total=100)  # 总任务数
for i in range(100):
    time.sleep(0.01)
    pbar.update(1)  # 每次更新进度
pbar.close()

3. 上下文管理器方式

from tqdm import tqdm
import time

# 使用 with 语句自动管理
with tqdm(total=100) as pbar:
    for i in range(100):
        time.sleep(0.01)
        pbar.update(1)

进度条自定义

基本自定义选项

from tqdm import tqdm
import time

for i in tqdm(range(100),
              desc="处理进度",      # 进度条描述
              ncols=80,            # 进度条宽度
              bar_format="{l_bar}{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}]",
              colour='green'):     # 颜色
    time.sleep(0.01)

进度条格式定制

from tqdm import tqdm
import time

# 自定义格式
custom_format = "{desc}: {percentage:3.0f}%|{bar:20}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}]"

for i in tqdm(range(100),
              desc="下载",
              bar_format=custom_format,
              ncols=100):
    time.sleep(0.01)

不同场景的应用

1. 文件处理进度

from tqdm import tqdm
import requests

# 下载文件显示进度
url = "https://example.com/large-file.zip"
response = requests.get(url, stream=True)
total_size = int(response.headers.get('content-length', 0))

with open('large-file.zip', 'wb') as file, tqdm(
    desc="下载",
    total=total_size,
    unit='iB',
    unit_scale=True,
    unit_divisor=1024,
) as bar:
    for data in response.iter_content(chunk_size=1024):
        size = file.write(data)
        bar.update(size)

2. 数据处理进度

from tqdm import tqdm
import pandas as pd
import time

# 处理 DataFrame 显示进度
df = pd.DataFrame({'data': range(1000)})

# 方法1:使用 tqdm.pandas()
tqdm.pandas()
result = df['data'].progress_apply(lambda x: x * 2)

# 方法2:手动控制
results = []
for idx, row in tqdm(df.iterrows(), total=len(df), desc="处理数据"):
    results.append(row['data'] * 2)
    time.sleep(0.001)

3. 多线程/多进程进度

from tqdm import tqdm
from concurrent.futures import ThreadPoolExecutor, as_completed
import time

def process_item(item):
    time.sleep(0.1)  # 模拟处理
    return item * 2

items = list(range(100))

# 多线程 + 进度条
with ThreadPoolExecutor(max_workers=5) as executor:
    futures = {executor.submit(process_item, item): item for item in items}
    
    for future in tqdm(as_completed(futures), total=len(items), desc="多线程处理"):
        result = future.result()

高级功能

1. 嵌套进度条

from tqdm import tqdm
import time

# 外层进度条
outer_bar = tqdm(range(5), desc="外层任务")

for i in outer_bar:
    # 内层进度条
    inner_bar = tqdm(range(10), desc=f"内层任务 {i+1}", leave=False)
    for j in inner_bar:
        time.sleep(0.05)
        inner_bar.set_postfix(状态=f"处理 {j}")
    inner_bar.close()

2. 动态描述和统计信息

from tqdm import tqdm
import time
import random

pbar = tqdm(range(100), desc="初始描述")

for i in pbar:
    time.sleep(0.02)
    
    # 动态更新描述
    pbar.set_description(f"处理项目 {i}")
    
    # 添加统计信息
    pbar.set_postfix(
        速度=f"{random.uniform(1.0, 10.0):.2f} items/s",
        成功率=f"{random.uniform(80, 100):.1f}%"
    )

3. Jupyter Notebook 支持

from tqdm.notebook import tqdm
import time

# Jupyter 专用进度条
for i in tqdm(range(100), desc="Jupyter 进度条"):
    time.sleep(0.01)

不同环境的进度条

1. 命令行进度条

from tqdm import tqdm
import time

# 标准命令行进度条
for i in tqdm(range(100)):
    time.sleep(0.01)

2. GUI 进度条

from tqdm.gui import tqdm
import time

# GUI 进度条(需要图形界面)
for i in tqdm(range(100)):
    time.sleep(0.01)

3. 笔记本环境

from tqdm.autonotebook import tqdm
import time

# 自动检测环境选择最佳进度条
for i in tqdm(range(100)):
    time.sleep(0.01)

实际应用示例

1. 批量文件处理

from tqdm import tqdm
import os
import shutil

def backup_files(source_dir, dest_dir):
    files = [f for f in os.listdir(source_dir) if f.endswith('.txt')]
    
    with tqdm(total=len(files), desc="备份文件") as pbar:
        for filename in files:
            src_path = os.path.join(source_dir, filename)
            dst_path = os.path.join(dest_dir, filename)
            
            shutil.copy2(src_path, dst_path)
            pbar.set_description(f"备份: {filename}")
            pbar.update(1)

# backup_files("./source", "./backup")

2. API 批量请求

from tqdm import tqdm
import requests
import time

def batch_api_requests(urls):
    results = []
    
    for url in tqdm(urls, desc="API 请求"):
        try:
            response = requests.get(url, timeout=10)
            results.append(response.status_code)
        except Exception as e:
            results.append(f"错误: {e}")
        
        time.sleep(0.5)  # 避免请求过快
    
    return results

# urls = ["https://httpbin.org/status/200"] * 10
# results = batch_api_requests(urls)

3. 机器学习训练进度

from tqdm import tqdm
import time
import random

def train_model(epochs=10, batches=100):
    # 训练进度条
    epoch_bar = tqdm(range(epochs), desc="训练周期")
    
    for epoch in epoch_bar:
        epoch_loss = 0
        
        # 批次进度条
        batch_bar = tqdm(range(batches), desc=f"周期 {epoch+1}", leave=False)
        
        for batch in batch_bar:
            # 模拟训练
            loss = random.uniform(0.1, 1.0)
            epoch_loss += loss
            
            # 更新批次信息
            batch_bar.set_postfix(
                损失=f"{loss:.4f}",
                平均损失=f"{(epoch_loss/(batch+1)):.4f}"
            )
            time.sleep(0.01)
        
        batch_bar.close()
        
        # 更新周期信息
        avg_loss = epoch_loss / batches
        epoch_bar.set_postfix(平均损失=f"{avg_loss:.4f}")

# train_model()

常见问题与解决方案

1. 进度条闪烁问题

from tqdm import tqdm
import time

# 使用 mininterval 和 miniters 减少刷新频率
for i in tqdm(range(1000), mininterval=0.5, miniters=10):
    time.sleep(0.001)

2. 处理异常情况

from tqdm import tqdm
import time

pbar = tqdm(range(100))

try:
    for i in pbar:
        if i == 50:
            raise ValueError("模拟错误")
        time.sleep(0.01)
        pbar.update(1)
except Exception as e:
    pbar.close()
    print(f"发生错误: {e}")

3. 自定义进度更新

from tqdm import tqdm
import time

total_items = 100
pbar = tqdm(total=total_items, desc="自定义进度")

processed = 0
while processed < total_items:
    # 模拟不固定进度的任务
    step = min(3, total_items - processed)  # 每次处理1-3个
    processed += step
    
    time.sleep(0.1)
    pbar.update(step)
    pbar.set_postfix(已处理=f"{processed}/{total_items}")

pbar.close()

性能优化技巧

from tqdm import tqdm
import time

# 1. 对于非常快速的操作,减少刷新频率
fast_loop = tqdm(range(10000), mininterval=0.1)

# 2. 使用 disable 参数控制是否显示进度条
debug_mode = False
loop = tqdm(range(100), disable=not debug_mode)

# 3. 对于文件操作,使用合适的 chunksize
def read_large_file(filename):
    with open(filename, 'r') as f:
        # 估算总行数(近似)
        total_lines = sum(1 for _ in f)
        f.seek(0)
        
        for line in tqdm(f, total=total_lines, desc="读取文件"):
            yield line.strip()

总结

tqdm 的主要优点:

  • 简单易用,一行代码即可添加进度条
  • 支持多种环境(命令行、GUI、Jupyter)
  • 高度可定制的外观和行为
  • 良好的性能,对程序运行影响小
  • 丰富的文档和活跃的社区

使用建议:

  • 对于耗时操作(> 1秒)使用进度条
  • 在循环内部避免频繁更新描述信息
  • 在多线程/进程环境中使用 tqdm.concurrent
  • 在生产环境中考虑使用 disable=True 关闭进度条

tqdm 是 Python 生态中最受欢迎的进度条库,合理使用可以大大提升用户体验和程序的可观测性。