یک بریکپوینت بیشرط روی فایلی با چند هزار سطر یعنی چند هزار بار زدن کلید ادامه. جوابش یک سطر است که کل تفاوت را میسازد:
if mm < -900: breakpoint()
حالا برنامه فقط وقتی میایستد که مقدار خراب باشد و شما مستقیم داخل همان تکرار هستید. breakpoint() از پایتون 3.7 در خود زبان است و لازم نیست چیزی ایمپورت شود؛ اگر متغیر محیطی PYTHONBREAKPOINT=0 باشد، همان سطر بدون هیچ کاری رد میشود، که یعنی میشود یک بریکپوینت شرطی را در کد نگه داشت و در اجرای عادی خاموش کرد.
پنج دستوری که نود درصد کار را میکنند
p nam, mmمقدار چند نام را چاپ میکند و جواب یک چندتایی است مثل('Astara', -999.0)nسطر بعدی همین تابع، بدون رفتن داخل فراخوانیهاsرفتن داخل فراخوانی همان سطرuیک قاب بالاتر، یعنی به تابعی که این را صدا زدهcادامه تا بریکپوینت بعدی
مهمترین این پنج تا u است. مقدار خراب معمولا در تابعی ساخته میشود که یک قاب بالاتر است، و بدون بالا رفتن فقط میبینید که مقدار غلط رسیده، نه اینکه از کجا. با u همانجا در حالت زنده به قاب صداکننده میروید و متغیرهایش را میبینید، همان چیزی که در برنامه چطور یادش میماند باید کجا برگردد فهرستش را دیدید.
وقتی برنامه ایستاده، هنوز یک مفسر کامل دارید
داخل جلسه اشکالزدایی هر عبارت پایتونی معتبر است، نه فقط دستورهای بالا. میشود یک تابع را با ورودی دیگری صدا زد و جوابش را دید، میشود یک مقدار را عوض کرد و اجرا را ادامه داد تا ببینید فرض شما درست بود یا نه. اگر نام متغیرتان با یک دستور یکی است، با p پیش از آن یا با ! صریح بگویید که عبارت است.
یک نکته که وقت زیادی میگیرد تا کشف شود: l چند سطر کد اطراف را نشان میدهد و ll کل تابع فعلی را. بدون این دو، آدم در جلسه اشکالزدایی نمیداند دقیقا کجای فایل ایستاده و به فایل باز در ویرایشگر نگاه میکند که ممکن است سطرهایش با نسخه در حال اجرا نخواند.
جایی که کار گیر میکند، اضافه کردن print است
در بیشتر کدهایی که به دست یک تیم میرسد، اثر دهها print فراموششده هست و همانها گواه ایناند که کسی هیچوقت بریکپوینت را امتحان نکرده. دلیلش هم قابل فهم است: print را همه بلدند و یاد گرفتن پنج دستور بالا نیم ساعت وقت میخواهد. هزینهاش این است که هر print یک بار اجرای دوباره کل برنامه است، و روی اسکریپتی که هر بار سه دقیقه طول میکشد، همان نیم ساعت در روز اول برمیگردد. قاعده عملی: اولین باری که برای یک باگ print دوم را اضافه میکنید، آن لحظه است که باید سراغ بریکپوینت بروید.
ابزار، و سالی که این حرف درست است
در سال ۲۰۲۶، breakpoint() در خود زبان است و رایگان، و جای import pdb; pdb.set_trace() را گرفته که پیش از پایتون 3.7 تنها راه بود و دو چیز اضافه در سطر داشت. برای همان کار با رابط گرافیکی، اشکالزدای VS Code روی همان مکانیزم مینشیند و بریکپوینت شرطی را بهجای کد، در خود ویرایشگر میگیرد؛ رایگان است و برای پایتون افزونه رسمی دارد. هر دو محلی کار میکنند و به شبکه نیازی ندارند.
پرسش بعدی این است که وقتی باگ روی سرور رخ میدهد و نمیشود جلوی برنامه را گرفت، چه چیزی جای این جلسه را میگیرد، که چه چیزی ثبت شود تا خرابی بعدی قابل تشخیص باشد است. و پیش از هر دوی اینها، خود گزارش خطا معمولا سطر را میگوید: سطری که مهم است معمولاً سطر اول نیست.