بیاید با هم روراست باشیم؛ همه‌ مون حداقل یک بار (و احتمالا هزاران بار!) وقتی کدمون کار نکرده یا خروجی عجیب‌وغریبی داده، سریع رفتیم سراغ روش باستانی و محبوب دیباگ کردن: یعنی پر کردن کل کد با print("here 1")، print("test") و print(x).

این روش شاید برای کد های کوچیک و چند خطی کار راه بندازه، اما وقتی پروژه بزرگ میشه، کنسول شما تبدیل میشه به یه آشغال ‌دونی از نوشته‌ های نامفهوم که خودتونم یادتون نمیاد کدوم print مال کدوم خط بوده! تازه بدتر از اون، وقتی کارتون تموم میشه باید کل کد رو بگردید تا این پرینت‌ های اضافه رو پاک کنید.

وقتشه که یکم حرفه‌ای ‌تر عمل کنیم و سطح دیباگ کردنمون رو ارتقا بدیم. تو این مقاله میخوایم با دو تا ابزار فوق ‌العاده و خفن پایتون آشنا بشیم که قراره جای print رو براتون پر کنن: IceCream و PySnooper.

۱. بستنی خوشمزه پایتون: IceCream 

کتابخونه IceCream (یا همون تابع ic) دقیقا همون چیزیه که تابع print باید از اول می‌بود! این ابزار برای چاپ کردن مقادیر متغیر ها در حین اجرای کد طراحی شده، اما با یک عالمه اطلاعات اضافه و مفید.

نصب IceCream

اول از همه باید نصبش کنید. ترمینال رو باز کنید و بنویسید:

pip install icecream

چرا IceCream از print بهتره؟

فرض کنید یه تابع دارید و میخواد خروجیش رو ببینید. با print معمولی فقط مقدار چاپ میشه، اما با ic، اسم متغیر، خطی که کد توش اجرا شده و مقدارش به صورت رنگی (تو ترمینال) چاپ میشه!

مثال با ()print:

def calculate_area(radius):
    area = 3.14 * (radius ** 2)
    return area

my_radius = 5
print(calculate_area(my_radius)) 

# خروجی: 78.5

همون مثال با ()ic:

from icecream import ic

def calculate_area(radius):
    area = 3.14 * (radius ** 2)
    return area

my_radius = 5
ic(calculate_area(my_radius))

# خروجی:
# ic| calculate_area(my_radius): 78.5

مزایای خفن IceCream:

  • اطلاعات کامل: خودش اسم تابع/متغیر و مقدارش رو با هم چاپ می‌کنه.

  • ردیابی اجرا: می‌تونید فقط بنویسید ic() بدون هیچ آرگومانی؛ بهتون میگه الان کدوم فایل، کدوم تابع و کدوم خط از کد داره اجرا میشه.

  • غیرفعال سازی راحت: وقتی دیباگ تموم شد، نیازی نیست تک‌تک ic ها رو پاک کنید. کافیه یک بار بنویسید ic.disable() تا همه‌شون خاموش بشن!

۲. کارآگاه خصوصی کدهای شما: PySnooper 

اگر IceCream برای دیدن مقادیر لحظه‌ای عالیه، PySnooper برای زمانیه که کدتون یه منطق پیچیده داره (مثل یه حلقه while یا for تو در تو) و می‌خواید خط به خط ببینید زیر هود (Under the hood) چه اتفاقی داره میفته.

پای‌اسنوپر مثل یه دوربین مخفیه که بالای سر تابع شما نصب میشه و هر اتفاقی که میفته (تغییر متغیرها، ورود به شرط‌ها، خروج از تابع) رو مو به مو گزارش می‌کنه.

نصب PySnooper

این یکی رو هم به راحتی با pip نصب کنید:

pip install pysnooper

چطور از کارآگاهمون استفاده کنیم؟

استفاده از PySnooper به شدت راحته. فقط کافیه دکوراتور (Decorator) @pysnooper.snoop() رو بالای تابعی که براتون دردسر درست کرده قرار بدید.

مثال: فرض کنید یه تابع داریم که میخواد اعداد زوج یک لیست رو جدا کنه:

import pysnooper

@pysnooper.snoop()
def get_even_numbers(numbers):
    evens = []
    for n in numbers:
        if n % 2 == 0:
            evens.append(n)
    return evens

my_list = [1, 2, 3, 4]
get_even_numbers(my_list)

خروجی PySnooper (حدودی): وقتی کد بالا رو اجرا کنید، یه خروجی دقیق و خط به خط می‌گیرید که نشون میده دقیقا تو هر میلی ‌ثانیه چه اتفاقی افتاده:

Source path:... my_script.py
10:45:30.123456 call         4 def get_even_numbers(numbers):
10:45:30.124000 line         5     evens = []
New var:....... evens = []
10:45:30.124500 line         6     for n in numbers:
New var:....... n = 1
10:45:30.125000 line         7         if n % 2 == 0:
... (و همینطور تا آخر اجرا خط به خط گزارش میده) ...

مزایای خفن PySnooper:

  • بدون نیاز به دستکاری کد: فقط یه دکوراتور اضافه میکنید و نیازی نیست داخل خود تابع پرینت بذارید.

  • ذخیره در فایل: میتونید بهش بگید گزارش رو تو کنسول شلوغ نکنه و بریزه تو یه فایل متنی: @pysnooper.snoop('debug.log')

  • ردیابی متغیرهای خاص: میتونید بهش بگید فقط حواسش به یه متغیر خاص یا یه آبجکت خاص باشه.

جمع‌بندی

واقعیت اینه که این دو تا ابزار رقیب هم نیستن، بلکه مکمل همدیگه‌اند:

  • اگر میخواید سریع مقدار یک متغیر رو چک کنید یا ببینید آیا برنامه وارد فلان شرط if شده یا نه، IceCream بهترین و سریع‌ترین انتخابه.

  • اما اگر یه الگوریتم پیچیده نوشتید که جواب غلط میده و اصلا نمیفهمید تو حلقه‌هاش داره چه اتفاقی میفته، PySnooper رو روشن کنید تا خط به خط کد رو براتون آنالیز کنه.

دیگه وقتشه عادت‌های قدیمی رو کنار بذاریم. دفعه بعدی که دستتون رفت رو کیبورد تا بنویسید print("salam")، یه لحظه مکث کنید و به جاش این ابزارهای حرفه‌ای رو امتحان کنید. مطمئن باشید که سرعت پیدا کردن باگ‌هاتون چند برابر میشه!