Hexo

凡事预则立,不预则废


  • Home

  • Tags

  • Archives

  • Navigation

  • Search

Python——tqdm库使用


整体说明

  • Tqdm 是一个快速、可扩展的 Python 进度条库,可以轻松地为你的循环添加一个智能进度条,让你直观地了解任务的执行进度
  • Tqdm 的名字来源于阿拉伯语 “taqaddum”,意为“进展”
  • Tqdm 可以通过一行 pip 指令安装:
    1
    pip install tqdm

Tqdm 的最常用用法(自动控制)

  • Tqdm 最核心的用法就是将可迭代对象包装在 tqdm() 函数中

    1
    2
    3
    4
    5
    6
    7
    from tqdm import tqdm
    import time

    # 循环 100 次,每次暂停 0.01 秒
    for i in tqdm(range(100)):
    time.sleep(0.01)
    # 100%|██████████| 100/100 [00:01<00:00, 83.01it/s]
    • 运行这段代码,你会看到一个实时的进度条,显示循环的完成百分比、已完成的迭代次数、总迭代次数、每秒迭代次数以及预计剩余时间

Tqdm 的常用参数

  • desc: 给进度条添加一个描述性前缀

    1
    2
    3
    for i in tqdm(range(100), desc="Processing data"):
    time.sleep(0.01)
    # Processing data: 100%|██████████| 100/100 [00:01<00:00, 82.70it/s]
  • total: 当可迭代对象没有 __len__ 方法时,你可以手动指定总迭代次数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import random

    # 假设有一个生成器
    def my_generator():
    for _ in range(100):
    yield random.randint(1, 10)

    # 因为生成器没有长度,所以需要指定 total
    for item in tqdm(my_generator(), total=100):
    time.sleep(0.01)
    # 100%|██████████| 100/100 [00:01<00:00, 81.47it/s]
  • unit: 设置迭代单位,例如 'B'(字节)、'it'(迭代)

    1
    2
    3
    4
    # 模拟文件下载进度条
    for i in tqdm(range(1024), unit='B', unit_scale=True, desc="Downloading file"):
    time.sleep(0.001)
    # Downloading file: 100%|██████████| 1.02k/1.02k [00:12<00:00, 83.3B/s]
    • unit_scale=True 会自动将单位转换为 K、M、G 等,让显示更友好
  • ncols: 设置进度条的宽度,可以是一个整数或 None(自动适应终端宽度)

    1
    2
    3
    for i in tqdm(range(100), ncols=80): # 固定宽度为 80 个字符
    time.sleep(0.01)
    # 100%|█████████████████████████████████████████| 100/100 [00:01<00:00, 83.97it/s]
  • inital: 设置初始进度,用于从中间恢复任务的场景,一般用于手动控制的场景,下面会介绍


Tqdm 手动控制用法

  • 在某些情况下,可能无法直接将可迭代对象传递给 tqdm,例如当你需要在一个循环中分步更新进度时
  • 这时可以使用 tqdm 的上下文管理器或手动控制

使用上下文管理器 (推荐)

  • 使用 with 语句可以确保进度条在循环结束后正确关闭

    1
    2
    3
    4
    5
    6
    7
    with tqdm(total=100, desc="Manual loop") as pbar:
    for i in range(100):
    # 你的任务代码
    time.sleep(0.01)
    # 手动更新进度条
    pbar.update(1)
    # Manual loop: 100%|██████████| 100/100 [00:01<00:00, 82.50it/s]
    • pbar.update(n) 会将进度条前进 n 步,注意超过以后继续更新会导致超出部分显示异常(不会报错)
      1
      2
      3
      4
      5
      6
      7
      with tqdm(total=100, desc="Manual loop") as pbar:
      for i in range(100):
      # 你的任务代码
      time.sleep(0.01)
      # 手动更新进度条
      pbar.update(2)
      # Manual loop: 200it [00:01, 165.95it/s]
  • 若使用 initial 参数,则代码示例如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    from tqdm import tqdm
    import time

    with tqdm(initial=50, total=100, desc="Manual loop") as pbar:
    for i in range(50):
    # 你的任务代码
    time.sleep(0.01)
    # 手动更新进度条
    pbar.update(1)
    # 开始就是下面这样
    # Manual loop: 50%|█████ | 50/100 [00:00<?, ?it/s]
    # 最终变成这样:
    # Manual loop: 100%|██████████| 100/100 [00:00<00:00, 81.43it/s]

手动创建和关闭

  • 如果不能使用上下文管理器,可以手动创建和关闭进度条
    1
    2
    3
    4
    5
    6
    7
    8
    pbar = tqdm(total=100)
    for i in range(100):
    # 你的任务代码
    time.sleep(0.01)
    # 更新进度条
    pbar.update(1)
    # 任务完成后手动关闭进度条
    pbar.close()

Tqdm 高级用法

tqdm.notebook for Jupyter/IPython(暂未测试)

  • 如果在 Jupyter Notebook 或 IPython 环境中,可以使用 tqdm.notebook 模块,它会生成一个更美观的 HTML 进度条
    1
    2
    3
    4
    5
    from tqdm.notebook import tqdm
    import time

    for i in tqdm(range(100)):
    time.sleep(0.01)

tqdm.pandas for Pandas(暂未测试)

  • Tqdm 可以轻松地与 Pandas 的 apply、groupby 等方法结合,为数据处理过程添加进度条
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import pandas as pd
    from tqdm.pandas import tqdm # 注意这里导入的是 tqdm.pandas 包

    tqdm.pandas(desc="Processing DataFrame")

    df = pd.DataFrame({'a': range(100000)})

    # 使用 progress_apply 替代 apply
    df['b'] = df['a'].progress_apply(lambda x: x * 2)

嵌套进度条

  • 当需要为嵌套循环添加进度条时,可以将内部循环的 tqdm 实例作为外部 tqdm 的子项

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    for i in tqdm(range(5), desc="Outer loop"):
    for j in tqdm(range(10), desc=f"Inner loop {i}", leave=False):
    time.sleep(0.01)
    # Outer loop: 0%| | 0/5 [00:00<?, ?it/s]
    # Inner loop 0: 0%| | 0/10 [00:00<?, ?it/s]
    # Inner loop 0: 90%|█████████ | 9/10 [00:00<00:00, 82.94it/s]
    # Outer loop: 20%|██ | 1/5 [00:00<00:00, 8.23it/s]
    # Inner loop 1: 0%| | 0/10 [00:00<?, ?it/s]
    # Inner loop 1: 90%|█████████ | 9/10 [00:00<00:00, 84.44it/s]
    # Outer loop: 40%|████ | 2/5 [00:00<00:00, 8.31it/s]
    # Inner loop 2: 0%| | 0/10 [00:00<?, ?it/s]
    # Inner loop 2: 90%|█████████ | 9/10 [00:00<00:00, 82.45it/s]
    # Outer loop: 60%|██████ | 3/5 [00:00<00:00, 8.26it/s]
    # Inner loop 3: 0%| | 0/10 [00:00<?, ?it/s]
    # Inner loop 3: 90%|█████████ | 9/10 [00:00<00:00, 80.50it/s]
    # Outer loop: 80%|████████ | 4/5 [00:00<00:00, 8.16it/s]
    # Inner loop 4: 0%| | 0/10 [00:00<?, ?it/s]
    # Inner loop 4: 80%|████████ | 8/10 [00:00<00:00, 79.85it/s]
    # Outer loop: 100%|██████████| 5/5 [00:00<00:00, 8.15it/s]
    • 注意 leave=False 参数,它会确保内部进度条在完成后立即消失,避免屏幕杂乱

Python——全局解释器锁


什么是 GIL?

  • 全局解释器锁(Global Interpreter Lock,GIL)是 Python 解释器(如 CPython)中的一个机制,它确保在同一时刻只有一个线程执行 Python 字节码
  • GIL 的存在意味着:即使在多核处理器上 ,多个线程也无法真正并行执行 Python 代码

GIL 存在的原因

  • GIL 的存在主要是为了保护 Python 解释器的内部状态,避免多线程同时修改导致的数据竞争问题
  • 由于 Python 的内存管理不是线程安全的,GIL 提供了一种简单的解决方案来保证线程安全

GIL对多线程的影响

  • GIL对多线程程序的影响取决于线程执行的任务类型:
    • CPU密集型任务 :这类任务主要是进行大量的计算,需要频繁使用CPU
      • GIL使得,即使使用多线程,多个 CPU 核心也无法同时执行 Python 代码
      • 多线程在 CPU 密集型任务上的表现可能比单线程更差,因为线程切换会带来额外的开销
    • I/O密集型任务 :这类任务主要是进行输入输出操作,如网络请求、文件读写等
      • 在执行 I/O 操作时,线程会释放 GIL,允许其他线程执行
      • 多线程在I/O密集型任务上可以显著提高性能

如何规避 GIL 的限制

  • 使用多进程(常用) :multiprocessing模块允许创建多个进程,每个进程都有自己的 Python 解释器和 GIL,因此可以真正并行执行 CPU 密集型任务
  • 使用 C 扩展(不常用) :将关键部分的代码用 C 语言实现,并在 C 扩展中释放 GIL。这样可以让C代码在多核处理器上并行执行
1…269270271…352
San Ye

San Ye

Stay Hungry. Stay Foolish.

704 posts
53 tags
© 2026 San Ye
Powered by Hexo
|
Theme — NexT.Gemini v5.1.4