بهجای حدس زدن، برنامه را وسط اجرا نگه دارید
بیشتر تازهکارها با print دیباگ میکنند: چند خط چاپ اضافه، اجرا، حدس، پاک کردن و دوباره. دیباگر یعنی برنامه را در یک خط مشخص متوقف کنید، همهی متغیرها را همان لحظه ببینید، قدمبهقدم جلو بروید و حتی عبارت دلخواه اجرا کنید. این کد گزارش ماهانه را ببینید که عدد غلط میدهد:
orders = [
{"created": "2025-04-02", "price": 57_000_000},
{"created": "2025-04-19", "price": 31_500_000},
{"created": "2025-05-03", "price": 12_000_000},
]
def monthly_total(orders):
totals = {}
for o in orders:
month = o["created"][:7]
breakpoint() # اجرا اینجا میایستد
totals[month] = o["price"] # باگ: جایگزین میکند، جمع نمیزند
return totals
print(monthly_total(orders)) # جمع 2025-04 باید 88,500,000 باشد
با اجرای فایل، پایتون در خط breakpoint() میایستد و اعلان (Pdb) ظاهر میشود:
> report.py(13)monthly_total()
-> totals[month] = o["price"] # باگ: جایگزین میکند، جمع نمیزند
(Pdb) p month, totals
('2025-04', {})
(Pdb) c
> report.py(13)monthly_total()
-> totals[month] = o["price"] # باگ: جایگزین میکند، جمع نمیزند
(Pdb) p totals
{'2025-04': 57000000}
(Pdb) n
> report.py(10)monthly_total()
-> for o in orders:
(Pdb) p totals
{'2025-04': 31500000} # همینجا باگ پیدا شد
(Pdb) q
درمان: totals[month] = totals.get(month, 0) + o["price"]، یا همان Counter درس پروژه.
فرمانهای پرکاربرد pdb
| فرمان | کار |
|---|---|
n (next) | اجرای خط فعلی و رفتن به خط بعد، بدون ورود به تابعها |
s (step) | ورود به داخل تابعی که در خط فعلی صدا زده میشود |
c (continue) | ادامه تا breakpoint بعدی |
p / pp | چاپ مقدار / چاپ مرتب dict و لیستهای بزرگ |
l / ll | نمایش کد اطراف / کل تابع فعلی |
w، u، d | پشتهی فراخوانی؛ بالا و پایین رفتن بین تابعها |
b 13 | گذاشتن breakpoint در خط ۱۳ |
q | خروج |
دیباگر VS Code
با افزونهی Python، روی شمارهی خط کلیک کنید (یا F9) تا نقطهی قرمز بنشیند و با F5 اجرا کنید. پنل Variables همهی متغیرها را نشان میدهد، Watch عبارت دلخواه را دنبال میکند و در Debug Console هر کد پایتونی را در همان لحظه اجرا میکنید. F10 معادل n و F11 معادل s است. برای برنامهی خط فرمان، آرگومانها را در .vscode/launch.json بدهید:
{
"version": "0.2.0",
"configurations": [
{
"name": "orders report",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/cli.py",
"args": ["report"],
"console": "integratedTerminal",
"justMyCode": true,
"env": {"PYTHONUTF8": "1"}
}
]
}
با راستکلیک روی نقطهی قرمز و Edit Breakpoint، شرط بگذارید (مثلاً o["price"] > 50_000_000) تا فقط سفارشهای مشکوک متوقف شوند؛ یا Logpoint بسازید که بدون توقف و بدون تغییر کد، پیامی مثل {month} چاپ کند.
نکتههایی که کمتر کسی میداند
- متغیر محیطی
PYTHONBREAKPOINT=0همهیbreakpoint()ها را بیاثر میکند؛ ولی بهتر است اصلاً در کد نمانند. قاعدهی T100 در ruff، breakpoint جامانده را پیش از commit پیدا میکند. - اگر متغیری به نام
n،cیاlدارید، تایپ نامش در pdb فرمان را اجرا میکند نه چاپ را؛ بنویسیدp nیا!n. python -m pdb -c continue cli.py reportبرنامه را عادی اجرا میکند و فقط وقتی استثنا رخ دهد، دیباگر را در همان نقطه باز میکند (post-mortem). در REPL هم بعد از خطاimport pdb; pdb.pm()همین کار را میکند.- فرمان
interactدر pdb یک REPL کامل با همهی متغیرهای محلی باز میکند؛ برای امتحان چند خط درمان پیش از تغییر فایل عالی است. - اگر VS Code نقطهی قرمز را خاکستری نشان میدهد و نمیایستد، معمولاً مفسر انتخابشده (Python: Select Interpreter) همان
.venvپروژه نیست، یا فایل در کتابخانهای است کهjustMyCodeآن را رد میکند.