آموزش پایتون - Python - Debugger (PDB)

پایتون یک ماژول داخلی به نام pdb برای عیب‌یابی (دیباگ) برنامه‌های پایتون ارائه می‌دهد. از ماژول pdb می‌توان برای تنظیم نقاط توقف (breakpoint)، حرکت در میان خطوط کد، بررسی مقدار متغیرها و ارزیابی عبارت‌ها استفاده کرد. در این فصل، نحوه استفاده از ماژول pdb برای دیباگ برنامه‌های پایتون را توضیح خواهیم داد.

مباحث زیر در این فصل پوشش داده خواهند شد −

  • ماژول pdb در پایتون
  • دستورات پایه در ترمینال pdb
  • مثالی از نحوه استفاده از ماژول pdb
  • بررسی نوع متغیر در زمان اجرا (Runtime)
  • دیباگ پس از وقوع خطا (Post-Mortem Debugging) با ماژول pdb
  • مدیریت نقاط توقف (Breakpoints) در ماژول pdb

ماژول pdb در پایتون

ماژول pdb یک ماژول داخلی در پایتون است که یک محیط دیباگ تعاملی برای برنامه‌های پایتون فراهم می‌کند. این ماژول در درون خود به عنوان کلاسی به نام Pdb تعریف شده که زیرکلاسی از کلاس bdb.Bdb است. مزیت اصلی دیباگر pdb این است که به‌طور کامل در ترمینال اجرا می‌شود؛ به این معنی که برای استفاده از آن نیازی به نصب هیچ نرم‌افزار اضافی یا IDE ندارید.

برای شروع دیباگ با pdb، ابتدا این ماژول را در اسکریپت پایتون خود وارد (import) کنید −

import pdb

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

دستورات پایه در ترمینال pdb

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

  • n (next) − اجرای خط بعدی کد.
  • s (step) − ورود به داخل فراخوانی یک تابع.
  • c (continue) − ادامه اجرای برنامه تا نقطه توقف بعدی.
  • l (list) − نمایش موقعیت فعلی در کد.
  • p (print) − چاپ مقدار یک متغیر.
  • q (quit) − خروج از دیباگر و پایان دادن به برنامه.
  • b (break) − تنظیم نقطه توقف در شماره خط یا تابعی مشخص.

برای مشاهده لیست کامل دستورات pdb، می‌توانید از دستور h در محیط تعاملی pdb استفاده کنید. این محیط به شکل زیر خواهد بود −

pdb help command

مثالی از نحوه استفاده از ماژول pdb

مثال زیر نشان می‌دهد چگونه می‌توان از pdb برای متوقف کردن اجرای برنامه در نقاطی خاص و بررسی مقادیر متغیرها استفاده کرد.

import pdb

def add(a, b):
    return a + b

def subtract(a, b):
    return a - b

pdb.set_trace()  # Set a breakpoint here
result = add(20, 30)
print("Addition Result:", result)

pdb.set_trace()  # Set another breakpoint here
result = subtract(20, 10)
print("Subtraction Result:", result)

هنگامی که اجرای برنامه به خط pdb.set_trace() برسد، متوقف شده و وارد ترمینال pdb می‌شود. بنابراین، خروجی برنامه به صورت زیر خواهد بود −

> /tmp/ipython-input-1706780559.py(11)<cell line: 0>()
      9 x = 10
     10 y = 20
---> 11 pdb.set_trace()  # Set a breakpoint here
     12 result = add(x, y)
     13 print("Addition Result:", result)

ipdb> c
Addition Result: 30

ipdb> c
Subtraction Result: 10

توضیح − در خروجی مشاهده می‌کنید که در این ترمینال، دستور c را برای ادامه اجرا تا نقطه توقف بعدی وارد کردیم. در نتیجه، نتیجه جمع دریافت شد و برنامه دوباره متوقف گردید. سپس مجدداً دستور c را فشردیم تا اجرا ادامه یابد و نتیجه تفریق چاپ شود.

بررسی نوع متغیر در زمان اجرا (Runtime)

برای بررسی نوع یک متغیر در زمان اجرا هنگام استفاده از pdb، می‌توانید از دستور whatis در محیط pdb استفاده کنید. مثال زیر نحوه استفاده از دستور whatis را نشان می‌دهد −

import pdb

a = 10
b = 20.5
c = "Hello, World!"

pdb.set_trace()  # Set a breakpoint here

خروجی برنامه به صورت زیر خواهد بود −

> /tmp/ipython-input-1057349253.py(7)<cell line: 0>()
      3 a = 10
      4 b = 20.5
      5 c = "Hello, World!"
      6 
----> 7 pdb.set_trace()  # Set a breakpoint here

ipdb> whatis a
<class 'int'>
ipdb> whatis b
<class 'float'>
ipdb> whatis c
<class 'str'>

دیباگ پس از وقوع خطا (Post-Mortem Debugging) با ماژول pdb

دیباگ Post-mortem به فرآیند تحلیل برنامه پس از کرش کردن (متوقف شدن ناگهانی) یا رسیدن به وضعیت استثنا (Exception) اشاره دارد. ماژول pdb می‌تواند برای انجام دیباگ پس از وقوع خطا با استفاده از تابع pdb.post_mortem() مورد استفاده قرار گیرد. می‌توانید این تابع را در داخل هر بلاک مدیریت استثنا (Exception Handler) در هر نقطه‌ای از کد خود فراخوانی کنید.

تابع pdb.post_mortem() شیء traceback را به عنوان آرگومان می‌پذیرد که می‌توانید آن را با استفاده از تابع sys.exc_info() به دست آورید. در ادامه مثالی آورده شده که نحوه استفاده از تابع pdb.post_mortem() را برای دیباگ پس از وقوع خطا نشان می‌دهد −

import pdb
import sys

def calculate_inverse(x):
    print(f"Calculating inverse for {x}:")
    result = 1 / x
    print(result)

try:
    calculate_inverse(10)
    calculate_inverse(0)  # This will raise error

except Exception:
    # This block is executed only after an exception (crash) occurs.
    print("\n An exception occurred! Starting post-mortem debugging... ")

    # Get the traceback object of the exception
    extype, exvalue, tb = sys.exc_info()
    
    # Launch the post-mortem debugger
    pdb.post_mortem(tb)

در این مثال، تابع calculate_inverse() برای محاسبه معکوس عدد صفر استفاده شده است. این کار باعث رخ دادن استثنای ZeroDivisionError می‌شود. وقتی استثنا رخ می‌دهد، برنامه وارد بلاک except خواهد شد. در اینجا تابع pdb.post_mortem(tb) را فراخوانی می‌کنیم تا نشست دیباگ پس از خطا آغاز شود. خروجی برنامه به صورت زیر خواهد بود −

Calculating inverse for 10:
0.1
Calculating inverse for 0:

 An exception occurred! Starting post-mortem debugging... 
> /tmp/ipython-input-1016125975.py(6)calculate_inverse()
      4 def calculate_inverse(x):
      5     print(f"Calculating inverse for {x}:")
----> 6     result = 1 / x
      7     print(result)
      8 

ipdb> p x
0

توضیح − در خروجی می‌توانید ببینید که برنامه درست در خطی که استثنا رخ داده، متوقف شده است. ما مقدار متغیر x را با استفاده از دستور p چاپ کردیم. به این ترتیب ایده روشنی به دست می‌آوریم که برنامه به دلیل تلاش برای تقسیم بر صفر کرش کرده است.

مدیریت نقاط توقف (Breakpoints) در ماژول pdb

پیش‌تر دیدیم که چگونه می‌توان با استفاده از تابع pdb.set_trace() نقاط توقف را تنظیم کرد. هنگام کار روی برنامه‌های بزرگ، اغلب نقاط توقف متعددی را در بخش‌های مختلف کد قرار می‌دهیم. بنابراین مدیریت صحیح این نقاط توقف بسیار حائز اهمیت است. در ادامه چند دستور برای مدیریت نقاط توقف در pdb آورده شده است −

  • break − دستور break برای تنظیم نقطه توقف در هر شماره خطی از طریق محیط pdb استفاده می‌شود. به عنوان مثال، break main.py:9 یک نقطه توقف در خط شماره 9 از فایل main.py قرار می‌دهد.
  • disable − دستور disable برای غیرفعال کردن یک نقطه توقف مشخص بر اساس شماره آن استفاده می‌شود. به عنوان مثال، disable 1 نقطه توقف شماره 1 را غیرفعال می‌کند.
  • enable − دستور enable برای فعال‌سازی مجدد نقطه توقفی که با دستور disable غیرفعال شده بود، به کار می‌رود. به عنوان مثال، enable 1 نقطه توقف شماره 1 را فعال می‌کند.
  • clear − دستور clear برای حذف یک نقطه توقف بر اساس شماره آن استفاده می‌شود. به عنوان مثال، clear 1 نقطه توقف شماره 1 را حذف می‌کند.

در ادامه مثالی آورده شده که نحوه مدیریت نقاط توقف در pdb را نشان می‌دهد −

import pdb
def multiply(a, b):
    return a * b
def divide(a, b):
    return a / b

pdb.set_trace()             # Set a breakpoint here
result1 = multiply(10, 20)

result2 = divide(10, 0)
print("Multiplication Result:", result1)

print("Division Result:", result2)

در این کد، با استفاده از تابع pdb.set_trace() یک نقطه توقف قرار داده‌ایم. وقتی برنامه به این خط برسد، متوقف شده و وارد نشست pdb می‌شود. خروجی برنامه به صورت زیر خواهد بود −

None
> /tmp/ipython-input-2031724579.py(7)<cell line: 0>()
      5     return a / b
      6 
----> 7 pdb.set_trace()             # Set a breakpoint here

ipdb> break main.py:8 
Breakpoint 1 at /tmp/ipython-input-2031724579.py:8
ipdb> break
Num Type         Disp Enb Where
1   breakpoint   keep yes at /tmp/ipython-input-2031724579.py:8
ipdb> disable 1
Disabled breakpoint 1 at /tmp/ipython-input-2031724579.py:8
ipdb> enable 1
Enabled breakpoint 1 at /tmp/ipython-input-2031724579.py:8

توضیح − در خروجی مشاهده می‌کنید که از دستور break در ترمینال برای ایجاد نقطه توقف در خط شماره 8 استفاده کرده‌ایم. سپس لیست نقاط توقف را با دستور break بدون آرگومان نمایش دادیم. پس از آن، نقطه توقف را با دستور disable غیرفعال و سپس دوباره با دستور enable آن را فعال کردیم.

نتیجه‌گیری

در این فصل، یاد گرفتیم که چگونه از ماژول pdb برای دیباگ برنامه‌های پایتون استفاده کنیم. دستورات پایه pdb، نحوه تنظیم و مدیریت نقاط توقف، روش بررسی نوع متغیرها در زمان اجرا و نحوه انجام دیباگ پس از وقوع خطا (Post-Mortem) را بررسی کردیم. ابزار دیباگ برای شناسایی و رفع مشکلات در پایگاه‌های کد بزرگ بسیار کاربردی است. با تمرین مناسب، می‌توانید به راحتی باگ‌های موجود در برنامه‌های پایتون خود را یافته و برطرف کنید.

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