tqdm - Intelligent Progress Bars
tqdm - 智能进度条
tqdm is the standard tool for monitoring long-running loops in Python. It has negligible overhead (about 60ns per iteration) and works everywhere: in the console, in Jupyter notebooks, and even in GUIs.
tqdm是Python中监控长时间运行循环的标准工具。它的开销微乎其微(每次迭代约60纳秒),且可在所有环境中使用:控制台、Jupyter笔记本甚至GUI界面。
- Monitoring long-running loops (simulations, data processing, ML training).
- Tracking progress of file downloads or I/O operations.
- Providing visual feedback in command-line tools.
- Integrating progress tracking into pandas operations (progress_apply).
- Monitoring parallel tasks in concurrent.futures or multiprocessing.
- Creating nested progress bars for hierarchical tasks (e.g., epochs and batches).
- 监控长时间运行的循环(模拟程序、数据处理、机器学习训练)。
- 跟踪文件下载或I/O操作的进度。
- 在命令行工具中提供可视化反馈。
- 将进度跟踪集成到Pandas操作中(progress_apply)。
- 监控concurrent.futures或multiprocessing中的并行任务。
- 为分层任务创建嵌套进度条(例如:训练轮次(epochs)和批次(batches))。
Reference Documentation
参考文档
The simplest way to use tqdm is to wrap any iterable:
for item in tqdm(iterable):
. It automatically calculates the length and estimates the time remaining.
使用tqdm最简单的方式是包装任何可迭代对象:
for item in tqdm(iterable):
。它会自动计算长度并估算剩余时间。
tqdm is written to be extremely fast. It uses smart algorithms to limit the number of display updates so it doesn't slow down your actual computation.
tqdm的设计追求极致快速。它采用智能算法限制显示更新次数,避免拖慢实际计算过程。
tqdm has specialized modules for different environments (Jupyter, Keras, Pandas, Slack/Telegram notifications).
tqdm针对不同环境提供了专用模块(Jupyter、Keras、Pandas、Slack/Telegram通知)。
python
from tqdm import tqdm
import time
python
from tqdm import tqdm
import time
For Jupyter Notebooks specifically:
针对Jupyter笔记本的专用导入:
from tqdm.notebook import tqdm
from tqdm.notebook import tqdm
Basic Pattern - Automatic Loop Tracking
基础模式 - 自动循环跟踪
python
import time
from tqdm import tqdm
python
import time
from tqdm import tqdm
Just wrap the range or list
只需包装range或列表
for i in tqdm(range(1000)):
time.sleep(0.01) # Simulate work
for i in tqdm(range(1000)):
time.sleep(0.01) # Simulate work
- Use desc - Add a description to the bar so you know exactly which process is running (
tqdm(range(10), desc="Processing")
).
- Use leave=False for nested loops - This cleans up the inner bars after they finish, preventing console clutter.
- Use the notebook version - In Jupyter, use
from tqdm.notebook import tqdm
for pretty HTML bars.
- Set total manually - If your iterator doesn't have a , provide the parameter manually.
- Integrate with Pandas - Use to see progress on .
- Close manual bars - If using the manual approach, always use a statement or call .
- 使用desc参数 - 为进度条添加描述,明确当前运行的进程(
tqdm(range(10), desc="Processing")
)。
- 嵌套循环使用leave=False - 内层进度条完成后自动清理,避免控制台混乱。
- 使用笔记本专用版本 - 在Jupyter中,使用
from tqdm.notebook import tqdm
获取美观的HTML进度条。
- 手动设置total参数 - 如果迭代器没有属性,手动提供参数。
- 与Pandas集成 - 使用在中查看进度。
- 手动创建的进度条需关闭 - 如果使用手动方式,务必使用语句或调用。
- Update too often - Avoid manual updates in tight loops (e.g., millions of updates per second); tqdm handles this automatically if you wrap the iterator.
- Print to console inside tqdm - Standard will break the bar. Use instead.
- Ignore overhead - While low, if your loop body is sub-microsecond, any overhead matters; process in batches instead.
- Forget ascii=True - If working on old terminals or Windows CMD without Unicode support, use to avoid garbled characters.
- 过于频繁更新 - 避免在紧凑循环中手动更新(例如:每秒数百万次更新);如果包装迭代器,tqdm会自动处理。
- 在tqdm内部使用print() - 标准会破坏进度条。请改用。
- 忽略开销 - 尽管开销很低,但如果循环体耗时不足微秒,任何开销都会有影响;建议批量处理。
- 忘记设置ascii=True - 如果在旧终端或无Unicode支持的Windows CMD中使用,设置避免乱码。
Anti-Patterns (NEVER)
反模式(绝对避免)
python
from tqdm import tqdm
import time
python
from tqdm import tqdm
import time
❌ BAD: Mixing print() and tqdm (Corrupts the bar)
❌ 错误:混合使用print()和tqdm(会破坏进度条)
for i in tqdm(range(5)):
print(f"Doing step {i}") # Bar jumps to next line
time.sleep(0.1)
for i in tqdm(range(5)):
print(f"Doing step {i}") # Bar jumps to next line
time.sleep(0.1)
✅ GOOD: Use tqdm.write()
✅ 正确:使用tqdm.write()
for i in tqdm(range(5)):
tqdm.write(f"Doing step {i}") # Bar stays at the bottom
time.sleep(0.1)
for i in tqdm(range(5)):
tqdm.write(f"Doing step {i}") # Bar stays at the bottom
time.sleep(0.1)
❌ BAD: Manual update without closing (Potential memory leak/UI hang)
❌ 错误:手动更新但不关闭(可能导致内存泄漏/UI卡顿)
pbar = tqdm(total=100)
for i in range(100):
pbar.update(1)
pbar = tqdm(total=100)
for i in range(100):
pbar.update(1)
Missing pbar.close()!
缺少pbar.close()!
✅ GOOD: Use context manager
✅ 正确:使用上下文管理器
with tqdm(total=100) as pbar:
for i in range(100):
pbar.update(1)
with tqdm(total=100) as pbar:
for i in range(100):
pbar.update(1)
❌ BAD: Wrapping an iterator with no length without 'total'
❌ 错误:包装无长度的迭代器却不设置'total'
tqdm(my_generator) # Shows count but no progress bar/ETA
tqdm(my_generator) # 仅显示计数,无进度条/ETA
Advanced Usage and Customization
高级用法与自定义
Descriptions and Statistics
描述与统计信息
python
pbar = tqdm(range(100))
for i in pbar:
# Update description dynamically
pbar.set_description(f"Processing Step {i}")
# Add custom stats (e.g., loss in ML)
pbar.set_postfix(loss=0.5/(i+1), accuracy=i/100)
time.sleep(0.05)
python
pbar = tqdm(range(100))
for i in pbar:
# 动态更新描述
pbar.set_description(f"Processing Step {i}")
# 添加自定义统计信息(例如:机器学习中的损失值)
pbar.set_postfix(loss=0.5/(i+1), accuracy=i/100)
time.sleep(0.05)
Manual Control (For Non-Iterative Work)
手动控制(适用于非迭代任务)
Useful for tracking bytes in file I/O or API calls
适用于跟踪文件I/O或API调用的字节数
with tqdm(total=1024, unit='B', unit_scale=True, desc="Downloading") as pbar:
# Simulate chunked download
for chunk_size in [256, 128, 512, 128]:
time.sleep(0.5)
pbar.update(chunk_size)
with tqdm(total=1024, unit='B', unit_scale=True, desc="Downloading") as pbar:
# 模拟分块下载
for chunk_size in [256, 128, 512, 128]:
time.sleep(0.5)
pbar.update(chunk_size)
Integration with Ecosystems
生态系统集成
Pandas Integration
Pandas集成
python
import pandas as pd
from tqdm import tqdm
python
import pandas as pd
from tqdm import tqdm
Initialize tqdm for pandas
为Pandas初始化tqdm
tqdm.pandas(desc="Cleaning Data")
df = pd.DataFrame({'val': range(10000)})
tqdm.pandas(desc="Cleaning Data")
df = pd.DataFrame({'val': range(10000)})
Use progress_apply instead of apply
使用progress_apply替代apply
result = df['val'].progress_apply(lambda x: x**2)
result = df['val'].progress_apply(lambda x: x**2)
Nested Progress Bars
嵌套进度条
Perfect for Epochs vs Batches in deep learning
非常适合深度学习中的训练轮次(Epochs)与批次(Batches)
for epoch in tqdm(range(3), desc="Epochs"):
for batch in tqdm(range(10), desc="Batches", leave=False):
time.sleep(0.05)
for epoch in tqdm(range(3), desc="Epochs"):
for batch in tqdm(range(10), desc="Batches", leave=False):
time.sleep(0.05)
Parallel Processing (concurrent.futures)
并行处理(concurrent.futures)
python
from concurrent.futures import ThreadPoolExecutor
from tqdm import tqdm
def work(n):
time.sleep(0.1)
return n * 2
data = range(50)
with ThreadPoolExecutor() as executor:
# Use tqdm to monitor map results
results = list(tqdm(executor.map(work, data), total=len(data)))
python
from concurrent.futures import ThreadPoolExecutor
from tqdm import tqdm
def work(n):
time.sleep(0.1)
return n * 2
data = range(50)
with ThreadPoolExecutor() as executor:
# 使用tqdm监控map结果
results = list(tqdm(executor.map(work, data), total=len(data)))
1. Large File Reader with Progress
1. 带进度条的大文件读取器
python
import os
def read_large_file(filepath):
"""Read a file while showing a progress bar based on bytes."""
file_size = os.path.getsize(filepath)
with tqdm(total=file_size, unit='B', unit_scale=True, unit_divisor=1024) as pbar:
with open(filepath, 'rb') as f:
for chunk in iter(lambda: f.read(4096), b''):
# Process chunk
pbar.update(len(chunk))
python
import os
def read_large_file(filepath):
"""Read a file while showing a progress bar based on bytes."""
file_size = os.path.getsize(filepath)
with tqdm(total=file_size, unit='B', unit_scale=True, unit_divisor=1024) as pbar:
with open(filepath, 'rb') as f:
for chunk in iter(lambda: f.read(4096), b''):
# Process chunk
pbar.update(len(chunk))
2. Scientific Simulation Suite
2. 科学模拟套件
python
def run_simulation_suite(configs):
"""Run multiple simulations and log failures."""
results = []
with tqdm(configs, desc="Suite") as pbar:
for config in pbar:
try:
res = run_single_sim(config)
results.append(res)
except Exception as e:
tqdm.write(f"Error in config {config}: {e}")
pbar.set_postfix(success=len(results))
return results
python
def run_simulation_suite(configs):
"""Run multiple simulations and log failures."""
results = []
with tqdm(configs, desc="Suite") as pbar:
for config in pbar:
try:
res = run_single_sim(config)
results.append(res)
except Exception as e:
tqdm.write(f"Error in config {config}: {e}")
pbar.set_postfix(success=len(results))
return results
3. Training Loop with Custom Postfix
3. 带自定义后缀的训练循环
python
def train_model(epochs, data_loader):
pbar = tqdm(range(epochs), desc="Training")
for epoch in pbar:
loss = compute_loss() # dummy
acc = compute_acc() # dummy
# Update the bar with current metrics
pbar.set_postfix(loss=f"{loss:.4f}", acc=f"{acc:.2%}")
python
def train_model(epochs, data_loader):
pbar = tqdm(range(epochs), desc="Training")
for epoch in pbar:
loss = compute_loss() # dummy
acc = compute_acc() # dummy
# 用当前指标更新进度条
pbar.set_postfix(loss=f"{loss:.4f}", acc=f"{acc:.2%}")
Performance Optimization
性能优化
The mininterval parameter
mininterval参数
By default, tqdm updates every 0.1 seconds. If your terminal is slow (e.g., over SSH or a legacy GUI), increase
to 1.0 or 5.0 to reduce network/I/O traffic.
python
for i in tqdm(range(1000000), mininterval=1.0):
pass
默认情况下,tqdm每0.1秒更新一次。如果你的终端速度较慢(例如:通过SSH连接或旧版GUI终端),可将
增加到1.0或5.0以减少网络/I/O流量。
python
for i in tqdm(range(1000000), mininterval=1.0):
pass
Disabling tqdm in Production
在生产环境中禁用tqdm
You can globally disable bars (e.g., when running in a CI/CD environment or a non-interactive log) by setting
.
你可以全局禁用进度条(例如:在CI/CD环境或非交互式日志中运行时),只需设置
。
Check for environment variable
检查环境变量
is_ci = os.environ.get('CI') == 'true'
for i in tqdm(range(100), disable=is_ci):
pass
is_ci = os.environ.get('CI') == 'true'
for i in tqdm(range(100), disable=is_ci):
pass
Common Pitfalls and Solutions
常见问题与解决方案
The "Double Bar" Glitch
“双进度条”故障
In Jupyter, sometimes bars don't close properly, leading to stacks of red/green bars.
在Jupyter中,有时进度条无法正确关闭,导致出现一堆红/绿进度条堆叠的情况。
✅ Solution: Always use a 'with' statement or try-finally
✅ 解决方案:始终使用'with'语句或try-finally
Or clear all instances if stuck:
若卡住,可清除所有实例:
from tqdm import tqdm
tqdm._instances.clear()
from tqdm import tqdm
tqdm._instances.clear()
Unicode Error on Windows
Windows下的Unicode错误
Windows CMD (non-Terminal) often struggles with the smooth progress blocks.
Windows CMD(非Terminal)通常无法正常显示平滑的进度块。
✅ Solution: Use ASCII characters only
✅ 解决方案:仅使用ASCII字符
for i in tqdm(range(100), ascii=True):
pass
for i in tqdm(range(100), ascii=True):
pass
Multiple Bars Alignment
多个进度条对齐问题
If your bars are overlapping or jumping:
✅ Solution: Specify the position explicitly
✅ 解决方案:显式指定位置
Useful for manual multi-threading
适用于手动多线程场景
pbar1 = tqdm(total=100, position=0)
pbar2 = tqdm(total=100, position=1)
tqdm is a small addition to a script that provides immense psychological relief. It provides the "pulse" of your code, ensuring you are always aware of how your long-running scientific tasks are progressing.
pbar1 = tqdm(total=100, position=0)
pbar2 = tqdm(total=100, position=1)
tqdm是脚本中一个小小的添加,却能带来巨大的心理慰藉。它提供了代码的“脉搏”,让你始终清楚自己的长时间科学任务进展如何。