tqdm — правило для Cursor: прогресс-бары в Python
Файл правил для Cursor, который задаёт агенту единый стиль работы с tqdm: импорты, контекстные менеджеры, вывод в консоль и метрики в постфиксе.
.cursor/rules/tqdm.mdcЧто делает tqdm
Правило подключается к Cursor через .cursor/rules/tqdm.mdc и применяется к Python-файлам по маске **/*.py. Внутри — восемь разделов с парами примеров «плохо/хорошо»: импорт, контекстные менеджеры, ручные обновления, подписи и постфиксы, вывод через tqdm.write(), вложенные бары, интеграция с pandas и оговорки по производительности.
Агент перестаёт писать import tqdm и tqdm.tqdm(...), берёт from tqdm import tqdm, trange, оборачивает бары в with ... as pbar: и передаёт total при ручном pbar.update(n). Для print() внутри активного бара правило предлагает tqdm.write() — иначе индикатор рассыпается. Для вложенных циклов советует leave=False, для байтов — unit="B" и unit_scale=True.
Производительность — отдельный пункт: на очень быстрых циклах правило советует обновлять бар пачками, а не каждую итерацию. tqdm.pandas() регистрирует .progress_apply() в DataFrame, tqdm.auto сам выбирает вывод для терминала или Jupyter. Без установленного пакета tqdm примеры из правила не запустятся — это повод поставить зависимость заранее.
Какие задачи решает
- привести прогресс-бары в проекте к одному стилю
- убрать из кода сломанные индикаторы после
print() - закрывать бар даже при исключении внутри цикла
- подписать бары для загрузки файлов и обучения модели
- подружить прогресс с pandas и Jupyter-ноутбуками
Примеры запросов агенту
- Оберни цикл обучения в прогресс-бар по правилу tqdm: контекстный менеджер и
set_postfixс лоссом. - Замени
print()внутри цикла наtqdm.write(), чтобы бар не ломался. - Добавь прогресс к
df.progress_applyи настрой вложенные бары сleave=False.
Как установить tqdm
Вручную: положить файлы
.cursor/rules/tqdm.mdcВо frontmatter: description, globs, alwaysApply
Вручную: положить файлы
.claude/rules/tqdm.mdПоле paths во frontmatter ограничивает файлы: globs из источника → paths
AGENTS.md
Codex читает AGENTS.md: вставьте текст правила туда
Вручную: положить файлы
.github/instructions/tqdm.instructions.mdПоле applyTo задаёт, к каким файлам применять: globs из источника → applyTo
Вручную: положить файлы
.devin/rules/tqdm.mdВручную: положить файлы
.clinerules/tqdm.mdПо шагам, с командами для каждой платформы: Cursor rules: файлы .mdc, четыре режима и замена .cursorrules
Вопросы о tqdm
Как установить правило tqdm в Cursor?
Скопируйте файл .cursor/rules/tqdm.mdc в каталог .cursor/rules своего проекта. Cursor подхватит его автоматически и применит к файлам по маске **/*.py.
Что делает это правило?
Задаёт агенту Cursor набор практик для библиотеки tqdm: прямые импорты, контекстные менеджеры вместо ручного close(), обязательный total при ручных обновлениях и вывод через tqdm.write().
Почему нельзя использовать print() при активном баре?
Он перебивает вывод tqdm и разваливает индикатор. Правило требует tqdm.write(), который печатает сообщение, не ломая строку прогресса.
Исходный текст
tqdm.mdc · CC0-1.0
---
description: This guide defines best practices for using the `tqdm` library to implement clear, efficient, and robust progress bars in Python applications, ensuring consistent user feedback and maintainable code.
globs: **/*.py
---
# tqdm Best Practices
`tqdm` is the definitive library for adding progress bars to Python applications. It's lightweight, fast, and works across various environments (terminal, Jupyter). This guide outlines the mandatory practices for its use.
## 1. Import Strategy
Always import `tqdm` directly from the library for clarity. Use `trange` as a convenient shortcut for `tqdm(range(N))`.
❌ BAD: Generic import
```python
import tqdm
for i in tqdm.tqdm(range(100)):
pass
```
✅ GOOD: Direct and clear imports
```python
from tqdm import tqdm, trange
for i in trange(100): # Use trange for simple range loops
pass
data = [1, 2, 3] * 10
for item in tqdm(data, desc="Processing items"): # Use tqdm for iterables
pass
```
## 2. Prefer Context Managers
Use `tqdm` as a context manager (`with ... as pbar:`) whenever possible. This ensures the progress bar is properly closed and resources are released, even if exceptions occur.
❌ BAD: Manual `close()` (prone to errors)
```python
pbar = tqdm(total=100)
for i in range(100):
pbar.update(1)
# What if an error occurs here? pbar.close() might be skipped.
pbar.close()
```
✅ GOOD: Context manager for robust cleanup
```python
with tqdm(total=100, desc="Calculating") as pbar:
for i in range(100):
# Simulate work
if i == 50:
# Example of an error, pbar will still close
# raise ValueError("Something went wrong!")
pass
pbar.update(1)
```
## 3. Manual Updates for Non-Iterables or Custom Logic
When wrapping an iterable isn't feasible (e.g., callbacks, async operations, or custom progress logic), use `pbar.update(n)`. **Always provide `total`** when using manual updates.
❌ BAD: Missing `total` with manual updates (bar won't show percentage/ETA)
```python
pbar = tqdm(desc="Downloading")
# ... later in a callback ...
pbar.update(chunk_size)
```
✅ GOOD: Explicit `total` for manual updates
```python
import time
import random
file_size = 1024 * 1024 * 50 # 50 MB
downloaded_bytes = 0
with tqdm(total=file_size, unit="B", unit_scale=True, desc="Downloading file") as pbar:
while downloaded_bytes < file_size:
chunk = random.randint(1024, 1024 * 10) # Simulate chunk download
chunk = min(chunk, file_size - downloaded_bytes)
downloaded_bytes += chunk
pbar.update(chunk)
time.sleep(0.01)
```
## 4. Use Descriptive Labels and Postfix Information
Enhance readability by providing a `desc` (description) and dynamic `postfix` information. `set_description()` and `set_postfix()` are preferred for updating these dynamically.
❌ BAD: Static or cluttered description
```python
for epoch in tqdm(range(10), desc="Epoch"):
loss = 0.5 - epoch * 0.01
# This doesn't update dynamically without re-creating the bar
for batch in tqdm(range(100), desc=f"Epoch {epoch} Loss: {loss:.4f}", leave=False):
pass
```
✅ GOOD: Dynamic description and postfix updates
```python
import random
for epoch in tqdm(range(10), desc="Training Epochs"):
total_loss = 0.0
for batch in trange(100, desc=f"Batch {epoch+1}", leave=False):
current_loss = random.uniform(0.1, 0.5)
total_loss += current_loss
# Update postfix with real-time metrics
tqdm.set_postfix(loss=f"{current_loss:.4f}", avg_loss=f"{total_loss/(batch+1):.4f}")
# Simulate work
time.sleep(0.005)
```
## 5. Handle Output with `tqdm.write()`
Never use `print()` directly when a `tqdm` bar is active. It will corrupt the progress bar display. Use `tqdm.write()` instead, which intelligently prints messages without interfering.
❌ BAD: Corrupts progress bar
```python
for i in trange(10):
if i == 5:
print("Mid-loop message!") # This will mess up the bar
time.sleep(0.1)
```
✅ GOOD: Preserves progress bar integrity
```python
for i in trange(10, desc="Processing"):
if i == 5:
tqdm.write("Mid-loop message: Halfway there!")
time.sleep(0.1)
```
## 6. Fine-tune Display Options
Use `leave=False` for inner loops to remove them upon completion, keeping the terminal clean. Leverage `unit`, `unit_scale`, and `dynamic_ncols` for better presentation.
❌ BAD: Cluttered terminal with nested bars
```python
for i in tqdm(range(3), desc="Outer"):
for j in tqdm(range(5), desc="Inner"): # leave=True by default
time.sleep(0.05)
```
✅ GOOD: Clean nested bars and scaled units
```python
for i in tqdm(range(3), desc="Outer Loop"):
for j in tqdm(range(5), desc="Inner Loop", leave=False): # Bar disappears after inner loop finishes
time.sleep(0.05)
# Example with units
with tqdm(total=100_000_000, unit="B", unit_scale=True, dynamic_ncols=True, desc="Transferring") as pbar:
for _ in range(100):
pbar.update(1_000_000)
time.sleep(0.01)
```
## 7. Integrate with Data Science Libraries
`tqdm.pandas()` and `tqdm.auto` provide seamless integration for common data science workflows.
### Pandas DataFrames
Use `tqdm.pandas()` to add a `.progress_apply()` method to DataFrames.
```python
import pandas as pd
from tqdm.auto import tqdm # Use tqdm.auto for notebook compatibility
tqdm.pandas() # Register tqdm with pandas
df = pd.DataFrame({'col': range(100000)})
# Applying a function with a progress bar
df['new_col'] = df['col'].progress_apply(lambda x: x * 2)
```
### Jupyter Notebooks
`tqdm.auto` automatically detects if it's running in a Jupyter environment and uses the appropriate display.
```python
# In a .py file that might be run in a notebook or terminal
from tqdm.auto import tqdm, trange
def long_running_task():
for i in trange(100, desc="Auto-detected progress"):
time.sleep(0.01)
long_running_task()
```
## 8. Performance Considerations
`tqdm` is highly optimized, but for extremely fast loops (e.g., millions of iterations per second), consider batching updates or disabling the bar if not strictly necessary.
```python
# For loops where each iteration is extremely fast
total_iterations = 10_000_000
batch_size = 1000
with tqdm(total=total_iterations, desc="Batch Processing") as pbar:
for i in range(0, total_iterations, batch_size):
# Perform batch_size operations here
# ...
pbar.update(batch_size) # Update once per batch
```
© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc