معرفی 5 ابزار برای کمک به دیباگ در برنامه های پایتون

تقریبا غیرممکنه که ما برنامه‌ای بنویسیم و در اجرای اول آن، به لیست بزرگی از مشکلات برنخوریم که نیاز به حل کردن دارند، معمولا در پروسه حل کردن این مشکلات است که ما به اهمیت پیدا کردن راه‌های بهینه‌تر و سریع‌تری برای پیدا کردن این مشکلات پی می‌بریم.

در این پست می‌خواهیم که شما رو با چندتا از ابزارهایی که می‌توانند به شما در پیدا کردن این مشکلات کمک کنند آشنا کنیم. سطح این ابزارها متفاوت است و برای حل مشکلات در سطوح متفاوتی مورد استفاده قرار می‌گیرند.

1 – استفاده از print و بررسی نتایج

استفاده از این ابزار احتمالا برای بسیاری از برنامه‌نویسان با سطح حتی کمی بالاتر از تازه‌کار خیلی بدیهی و اولیه است، ولی این پیش‌‌پاافتادگی آن از موثر بودن آن کم نمی‌کند و برای کامل بودن مبحث ذکر آن خالی از لطف نیست.

راحت ترین راه برای پیدا کردن یک مشکل، استفاده از print برای نشان دادن مقدار متغیرهایمان و مقایسه آنها با مقداری که از هر متغیر انتظار داریم است.

در مثال زیر، اگر به مشکلی بربخوریم می توانیم متغیری که به آن شک داریم را با print چاپ کرده و با مقداری که انتظار داریم مقایسه کنیم و براساس این مقایسه، راه حلی برای مشکلمان بیابیم.

def divide100(num):
    n = int(num)
    return 100 / n

print(divide100('Yang'))
# Traceback (most recent call last):
# ...
# ValueError: invalid literal for int() with base 10: 'Yang'

در این مثال به ValueError بر می‌خوریم که ممکن است ندانیم به چه علت است، با استفاده از یک print در تابع می‌توانیم پی ببریم که مشکل ما به علت تقسیم یک مقدار غیر از int بر 100 است.

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

2 – استفاده از assert و بررسی نتایج

هرجایی که از print برای کمک به پروسه دیباگ استفاده می‌شود، می‌توانیم ازassert هم استفاده کنیم.

def divide(num):
    n = int(num)
    return 100 / n

print(divide('Yang'))

در این مثال هم مانند مثال قبلی به مشکل برخواهیم خورد، ولی با استفاده از assert می‌توانیم عبارتی تعیین کنیم که در صورتی که این عبارت False باشد، به ما یک AssertionError بازگردانده شود.

برای حل مشکل این مثال، برای حالتی که ورودی غیر int است عبارتی را در نظر می‌گیریم و کد ما به صورت زیر می‌شود :

def divide(num):
    assert type(num) == int, 'num must be a number'
    n = int(num)
    return 100 / n

(در این حالت اگر ورودی ما int نباشد عبارت type(num) == int غلط خواهد بود و عبارتی که بعد از آن تعیین کرده‌ایم به عنوان AssertionError به ما بازگردانده می‌شود )

print(divide('Yang'))
# Traceback (most recent call last):
#   ...
# AssertionError: num must be a number

print(divide(100))
#1.0

می‌بینیم که وقتی ورودی ما به صورت string بود و به ما AssertionError داده شد ولی وقتی int بود بدون مشکلی انجام شد.

بعد از اتمام دیباگ‌ می‌توانیم با عبارت زیر تمامی assert ها را بی‌اثر کنیم :

python -0 assert.py

در این حالت اگر باز هم ورودی اشتباه باشد، دیگر AssertionError نخواهیم داشت بلکه مثل حالت عادی به یک ValueError برخواهیم خورد.

3 – استفاده از logging module

پایتون یک ماژول بسیار پراستفاده به نام logging دارد. با استفاده از logging به جای print و یا assert امکانات بیشتری را برای دیباگ در اختیار ما قرار داده می‌شود. با کمک این ماژول می توانیم مشکلات برنامه را بهتر در نظر داشته باشیم.

در مثال زیر، پیام های log را در یک فایل خارجی پرینت می‌کنیم و دیگر نیازی به خروجی گرفتن در کنسول محل اجرای برنامه نیست (تنها عبارتی که در قسمت warning ذکر شده در کنسول مشاهده خواهد شد)

import logging
logging.basicConfig(filename='test.log', filemode='w', format='%(name)s - %(levelname)s - %(message)s')
logging.warning('This will get logged to a file')

اگر اطلاعات موردنظر ما زیاد باشند و یا خواندن همه آنها به طور یک جا و در کنسول راحت نباشد، با این روش کار خودمان را خیلی راحت تر خواهیم کرد.

4 – استفاده از pdb

چهارمین ابزار کمک‌کننده در دیباگ، دیباگر pdb خود پایتون است. به کمک آن می‌توانیم برنامه را در مراحل تک قسمتی اجرا کنیم و وضعیت برنامه را در هر مرحله چک کنیم. ابزارهای دیگری هم شبیه این ابزار وجود دارند، مانند web-pdb و یا pudb، ولی در اکثر مواقع pdb کار مورد نیاز ما را انجام می دهد.

یک مثال ساده

برای مثال می توانیم از pdb استفاده کنیم تا برنامه زیر را مرحله به مرحله اجرا کنیم :

s = '0'
 n = int(s)
 print(1000 / n)

ابتدا باید به کمک pdb فایل برنامه test.py را در ترمینال طبق روش زیر اجرا کنیم:

$ python -m pdb test.py

حال خط اول برنامه ما در حال اجرا است :

> /home/yang/test.py(1)<module>()
 -> s = '0'

می توانیم با وارد کردن 1 کل کد را مشاهده کنیم :

(Pdb) 1
 1 -> s = '0'
 2     n = int(s)
 3     print(1000 / n)

با هر دفعه وارد کردن دستور n، خط بعدی کد ما اجرا خواهد شد :

(Pdb) n
 > /home/yang/test.py(2)<module>()
 -> n = int(s)

 (Pdb) n
 > /home/yang/test.py(3)<module>()
 -> print(1000 / n)

 (Pdb) n
 ZeroDivisionError: division by zero
 > /home/yang/test.py(3)<module>()
 -> print(1000 / n)

در هرکدام از مراحل ما می توانیم با وارد کردن دستور p و نام یک متغیر در ادامه آن، مقدار آن را بررسی کنیم :

(Pdb) p s
 '0'
 (Pdb) p n
 0

اگر کد ما بیشتر از 4 – 5 خط باشد، شروع از خط اول و تک تک پایین رفتن با دستور n می تواند بسیار وقت‌گیر باشد. می‌توانیم با استفاده از تابع pdb.set_trace() یک breakpoint در کدمان قرار دهیم که خواندن کد ما از همان محل شروع شود. برای مثال اگر کد ما به صورت زیر باشد :

import pdb
 
 s = '0'
 n = int(s)
 pdb.set_trace() 
 print(1000 / n)

با اجرای برنامه در محیط pdb مستقیم و بدون نیاز به دستورات اضافه، به خطی که در آن set_trace را قرار داده‌ایم خواهیم‌ رفت و کار ما خیلی راحت‌تر خواهد بود :

> /home/yang/test.py(7)<module>()
 -> print(1000 / n)
 (Pdb)

دستور breakpoint()

از نسخه 3.7 پایتون یک دستور پیش فرض درون خود پایتون قرار داده شد که کاملا می تواند جایگزین set_trace شود،در حالتی که از این دستور به جای set_trace استفاده کنیم، کد ما به صورت زیر خواهد بود :

s = '0'
 n = int(s)
 breakpoint()
 print(1000 / n)

نتیجه استفاده از این دستور و طرز استفاده از آن کاملا با pdb.set_trace() یکسان است، چون ()breakpoint باعث صدا زدن دستور sys.breakpointhook() می شود و این دستور به طور پیش فرض pdb.set_trace() را صدا می زند.

استفاده از breakpoint فوائد دیگری هم دارد :

  • با استفاده از breakpoint نیاز به import کردن ماژول pdb نداریم و کد خیلی کم کوتاه تر می شود.
  • فایده مهم‌تر استفاده از این دستور این است که اگر دیگر مایل به استفاده از pdb نبودیم و خواستیم آن را با ابزار دیباگر دیگری جایگزین کنیم، نیازی به تغییر در کدمان برای حذف دستورات خاص به pdb نداریم و کدمان بدون تغییر قابل استفاده است.

برای مثال اگر بخواهیم از web-pdb (و یا هر ابزار دیباگر دیگری) استفاده کنیم که برای مورد استفاده ما مناسب‌تر است، در حالت قبلی باید تک تک دستورات pdb.set_trace() را به دستور web_pdb.set_trace() (و یا هر عبارت جایگزین دیگری که در آن ابزار برای دیباگ استفاده می شود) تبدیل می کردیم. با استفاده از breakpoint هیچ نیازی به تغییر کد نداریم، فقط باید متغیر PYTHONBREAKPOINT را با توجه به ابزار مورد استفاده همانند مثال زیر تغییر دهیم :

$ PYTHONBREAKPOINT = web_pdb.set_trace python3.7

همچنین می توانیم مقدار این متغیر را برابر صفر قرار دهیم تا برنامه ما در حالت عادی اجرا شود و تمامی breakpoint ها در نظر گرفته نشوند :

$ PYTHONBREAKPOINT = 0 python3.7

5 – استفاده از امکانات IDE

اگر علاقه به استفاده از IDE از برای نوشتن کدهای خود دارید، تعیین breakpoint ها و اجرای خط به خط کدها در این محیط ها بسیار ساده تر است.

با تعیین breakpoint به کمک یک IDE دیگر نیاز به وhرد کردن دستورات اضافه ای نیست و خود برنامه همانند breakpoint که به کمک pdb قرار داده شد عمل می کند.

از IDE های شناخته شده برای پایتون می توان به موارد زیر اشاره کرد :

  • برنامه PyCharm : این IDE از ابتدا برای استفاده توسط برنامه نویسان پایتون ساخته شده است و IDE جامعی برای کار با پایتون است.
  • برنامه Visual Studio Code : اگر با برنامه نویسی آشنایی قبلی داشته باشید احتمالا این code editor را می‌شناسید. می‌توانید با نصب افزونه‌های مناسب در این برنامه به همراه افزونه‌ی پایتون، به عنوان یه محیط مناسب برای توسعه‌ی برنامه‌های خودتون در پایتون از آن استفاده کنید .


5 ابزار برای کمک به دیباگ به شما معرفی کردیم، ولی گاهی بهترین ابزار برای این‌ کار قلم و کاغذ است. در خیلی از موارد نوشتن فلوچارت برنامه و ارتباطات بین کلاس‌ها و قسمت‌‍‌های مختلف یک کد، می تواند کمک به‌سزایی به فهم بهتر و پیدا کردن مشکلات احتمالی آن کد بکند، این روش را هم از یاد نبرید.


امیر هستم از ایران پایتونیرز، ممنونم از وقتی که برای خوندن این پست گذاشتید.

دیباگ کردن یکی از کارهای روزمره‌ای است که یک برنامه‌نویس باید انجام دهد و آشنایی بهتر با ابزارهای این کار می‌تواند کار برنامه‌نویس را بسیار راحت‌تر کند.امیدواریم که در این مطلب با ابزار جدیدی آشنا شده باشید و راحت‌تر به دیباگ کردن برنامه‌هاتون بپردازید.

برای دیدن ویدیو‌های آموزشی دیگری که دوستانم برای شما ساخته‌اند، می‌تونید به کانال ما در آپارات، یوتیوب، تلگرام یا اینستاگرام مراجعه کنید.

منبع : techtofreedom