وبلاگ رسانگار
با ما حرفه ای باشید

سرور مجازی NVMe

اشکال زدایی برنامه های پایتون با ماژول PDB

0 11
زمان لازم برای مطالعه: 9 دقیقه


معرفی

در این آموزش قصد داریم روش استفاده از پایتون را بیاموزیم PDB ماژول برای اشکال زدایی برنامه های پایتون. اشکال زدایی به process حذف خطاهای نرم افزاری و سخت افزاری از یک برنامه نرم افزاری. PDB مخفف “Python Debugger” است و یک دیباگر کد منبع تعاملی داخلی با طیف گسترده ای از ویژگی ها، مانند توقف یک برنامه، مشاهده مقادیر متغیر در نمونه های خاص، تغییر آن مقادیر و غیره است.

در این مقاله، متداول ترین قابلیت های مورد استفاده ماژول PDB را پوشش خواهیم داد.

زمینه

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

راه های مختلفی برای اشکال زدایی یک برنامه نرم افزاری وجود دارد. یک روش بسیار رایج استفاده از “print” در موارد مختلف کد خود را بیان می کند تا ببینید در حین اجرا چه اتفاقی می افتد. با این حال، این روش دارای مشکلات زیادی است، مانند اضافه کردن کد اضافی که برای استفاده از آن استفاده می شود. print مقادیر متغیرها و غیره. در حالی که این رویکرد ممکن است برای یک برنامه کوچک کار کند، ردیابی این تغییرات کد در یک برنامه بزرگ با خطوط کد زیادی که در فایل های مختلف پخش شده است، می تواند به یک مشکل بزرگ تبدیل شود. دیباگر آن مشکل را برای ما حل می کند. این به ما کمک می کند تا منابع خطا را در یک برنامه با استفاده از دستورات خارجی پیدا کنیم، بنابراین هیچ تغییری در کد ایجاد نمی شود.

توجه داشته باشید: همانطور که در بالا ذکر شد، PDB یک ماژول داخلی پایتون است، بنابراین نیازی به نصب آن از منبع خارجی نیست.

دستورات کلیدی

برای درک دستورات یا ابزارهای اصلی که در PDB در اختیار داریم، بیایید یک برنامه پایه پایتون را در نظر بگیریم و سپس سعی کنیم با استفاده از دستورات PDB آن را اشکال زدایی کنیم. به این ترتیب با یک مثال خواهیم دید که هر دستور دقیقا چه کاری انجام می دهد.



operators = ('+', '-', '*', '/')
numbers = (10, 20)

def calculator():
    print("Operators available: ")
    for op in operators:
        print(op)

    print("Numbers to be used: ")
    for num in numbers:
        print(num)

def main():
    calculator()

main()

این هم خروجی اسکریپت بالا:

Operators available:
+
-
*
/
Numbers to be used:
10
20

من هیچ نظری در کد بالا اضافه نکرده ام، زیرا برای مبتدیان مناسب است و به هیچ وجه شامل مفاهیم یا نحو پیچیده نیست. تلاش برای درک “وظیفه” ای که این کد به آن دست می یابد مهم نیست، زیرا هدف آن شامل موارد خاصی بود تا همه دستورات PDB آزمایش شوند. روی آی تی. خوب پس، بیایید شروع کنیم!

استفاده از PDB مستلزم استفاده از رابط خط فرمان (CLI) است، بنابراین باید برنامه خود را از terminal یا خط فرمان

دستور زیر را در CLI خود اجرا کنید:

$ python -m pdb calc.py

در دستور بالا، نام فایل من است calc.py، بنابراین باید نام فایل خود را در اینجا وارد کنید.

توجه داشته باشید: -m یک پرچم است و به فایل اجرایی پایتون اطلاع می دهد که یک ماژول باید وارد شود. پس از این پرچم، نام ماژول وجود دارد که در مورد ما چنین است pdb.

خروجی دستور به شکل زیر است:

> /Users/junaid/Desktop/calc.py(3)<module>()
-> operators = ( '+', '-', '*', '/' )
(Pdb)

خروجی همیشه ساختار یکسانی خواهد داشت. با مسیر دایرکتوری به فایل کد منبع ما شروع می شود. سپس، در داخل پرانتز، شماره خط آن فایلی را که PDB در حال حاضر به آن اشاره می کند، نشان می دهد که در مورد ما “(3)” است. خط بعدی که با علامت “->” شروع می شود، نشان دهنده خطی است که در حال حاضر به آن اشاره شده است.

برای بستن اعلان PDB، به سادگی وارد کنید quit یا exit در اعلان PDB

چند نکته دیگر که باید توجه داشته باشید، اگر برنامه شما پارامترها را به عنوان ورودی می پذیرد، می توانید آنها را از طریق خط فرمان نیز عبور دهید. به عنوان مثال، اگر برنامه ما در بالا به سه ورودی از کاربر نیاز داشت، دستور ما به این صورت خواهد بود:

$ python -m pdb calc.py var1 var2 var3

در حال حرکت روی، اگر قبلاً اعلان PDB را از طریق بسته کرده بودید quit یا exit دستور، سپس فایل کد را از طریق PDB دوباره اجرا کنید. پس از آن، دستور زیر را در خط PDB اجرا کنید:

(Pdb) list

خروجی به شکل زیر است:

  1     # Filename: calc.py
  2
  3  -> operators = ('+', '-', '*', '/')
  4     numbers = (10, 20)
  5
  6     def calculator():
  7         print("Operators available: ")
  8         for op in operators:
  9             print(op)
 10
 11         print("Numbers to be used: ")
(Pdb)

این 11 خط اول برنامه شما را به شما نشان می دهد که “->” به سمت خط فعلی است که توسط دیباگر اجرا می شود. بعد، این دستور را در خط PDB امتحان کنید:

(Pdb) list 4,6

این دستور باید فقط خطوط انتخاب شده را نمایش دهد که در این مورد خطوط 4 تا 6 هستند.

  4     numbers = (10, 20)
  5
  6     def calculator():
(Pdb)

اشکال زدایی با نقاط شکست

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

پیشنهاد می‌کنیم بخوانید:  نحوه اجرای احراز هویت دو مرحله ای با PyOTP و Google Authenticator در برنامه Flask خود

ما گزینه های مختلف زیر را برای ایجاد نقاط شکست داریم:

  1. با شماره خط
  2. با اعلام عملکرد
  3. با یک شرط

برای اعلام نقطه شکست بر اساس شماره خط، دستور زیر را در اعلان PDB اجرا کنید:

(Pdb) break calc.py:8

این دستور یک نقطه شکست را در خط هشتم کد وارد می کند، که پس از رسیدن به آن نقطه، برنامه را متوقف می کند. خروجی این دستور به صورت زیر نشان داده می شود:

Breakpoint 1 at /Users/junaid/Desktop/calc.py: 8
(Pdb)

برای اعلام نقاط شکست روی یک تابع، دستور زیر را در خط PDB اجرا کنید:

(Pdb) break calc.calculator

برای درج نقطه شکست به این روش، باید آن را با استفاده از نام فایل و سپس نام تابع اعلام کنید. این خروجی زیر را دارد:

Breakpoint 2 at /Users/junaid/Desktop/calc.py:6

همانطور که می بینید، این نقطه شکست به طور خودکار شماره 2 را به خود اختصاص داده است و شماره خط یعنی 6 که تابع در آن اعلام شده است نیز نشان داده شده است.

نقاط شکست را نیز می توان با یک شرط اعلام کرد. در این صورت برنامه تا زمانی اجرا می شود که شرط نادرست باشد، و زمانی که شرط درست شود، مکث می کند. دستور زیر را در خط PDB اجرا کنید:

(Pdb) break calc.py:8, op == "*"

این مقدار را دنبال می کند op متغیر در طول اجرا و تنها زمانی می شکند که مقدار آن در خط 8 “*” باشد.

برای مشاهده تمام نقاط شکستی که به صورت لیست اعلام کرده ایم، دستور زیر را در اعلان PDB اجرا کنید:

(Pdb) break

خروجی به شکل زیر است:

Num Type         Disp Enb   Where
1   breakpoint   keep yes   at /Users/junaid/Desktop/calc.py: 8
2   breakpoint   keep yes   at /Users/junaid/Desktop/calc.py: 6
    breakpoint already hit 1 time
3   breakpoint   keep yes   at /Users/junaid/Desktop/calc.py: 8
    stop only if op == "*"
(Pdb)

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

(Pdb) disable 2

این کار نقطه شکست 2 را غیرفعال می کند، اما آن را از نمونه دیباگر ما حذف نمی کند.

در خروجی شماره نقطه شکست غیرفعال را مشاهده خواهید کرد.

Disabled breakpoint 2 at /Users/junaid/Desktop/calc.py:6
(Pdb)

اجازه دهید print لیست تمام نقاط شکست را دوباره برای دیدن Enb مقدار برای نقطه شکست 2:

(Pdb) break

خروجی:

Num Type         Disp Enb   Where
1   breakpoint   keep yes   at /Users/junaid/Desktop/calc.py:8
2   breakpoint   keep no    at /Users/junaid/Desktop/calc.py:4 # you can see here that the "ENB" column for #2 shows "no"
    breakpoint already hit 1 time
3   breakpoint   keep yes   at /Users/junaid/Desktop/calc.py:8
    stop only if op == "*"
(Pdb)

برای فعال کردن مجدد نقطه شکست 2، دستور زیر را اجرا کنید:

(Pdb) enable 2

و باز هم این خروجی است:

Enabled breakpoint 2 at /Users/junaid/Desktop/calc.py:6

حالا اگر شما print لیست تمام نقاط شکست از نو، Enb مقدار ستون برای نقطه شکست 2 باید دوباره “بله” را نشان دهد.

حالا بیایید روشن نقطه شکست 1، که همه آن را با هم حذف می کند.

(Pdb) clear 1

خروجی به صورت زیر است:

Deleted breakpoint 1 at /Users/junaid/Desktop/calc.py:8
(Pdb)

اگر دوبارهprint لیست نقاط شکست، اکنون باید فقط دو ردیف نقطه شکست را نشان دهد. بیایید خروجی دستور “break” را ببینیم:

Num Type         Disp Enb   Where
2   breakpoint   keep yes   at /Users/junaid/Desktop/calc.py:4
    breakpoint already hit 1 time
3   breakpoint   keep yes   at /Users/junaid/Desktop/calc.py:8
    stop only if op == "*"

دقیقا همان چیزی که انتظارش را داشتیم.

قبل از اینکه از این بخش جلو برویم، می‌خواهم به همه مواردی که هنگام اجرای کد تا نقطه شکست مشخص شده نمایش داده می‌شود، نشان دهم. برای انجام این کار، بیایید تمام نقاط شکست قبلی را پاک کنیم و نقطه شکست دیگری را از طریق اعلان PDB اعلام کنیم:

1. تمام نقاط شکست را پاک کنید

(Pdb) clear

پس از آن، “y” را تایپ کرده و “Enter” را بزنید. شما باید خروجی مانند زیر را ببینید:

Deleted breakpoint 2 at /Users/junaid/Desktop/calc.py:6
Deleted breakpoint 3 at /Users/junaid/Desktop/calc.py:8

2. نقطه شکست جدید را اعلام کنید

چیزی که ما می خواهیم به آن برسیم این است که کد باید تا نقطه ای اجرا شود که مقدار the num متغیر بزرگتر از 10 است. بنابراین اساساً، برنامه باید قبل از چاپ عدد “20” متوقف شود.

(Pdb) break calc.py:13, num > 10

3. کد را تا این نقطه شکست اجرا کنید

پیشنهاد می‌کنیم بخوانید:  محاسبه ریشه مربع یک عدد در پایتون

برای اجرای کد، از دستور “continue” استفاده کنید، که کد را تا زمانی که به نقطه شکست برسد یا تمام شود اجرا می کند:

(Pdb) continue

شما باید خروجی زیر را ببینید:

Operators available:
+
-
*
/
Numbers to be used:
10
> /Users/junaid/Desktop/calc.py(13)calculator()
-> print(num)

این دقیقاً همان چیزی است که انتظار داشتیم، برنامه تا آن نقطه اجرا می‌شود و سپس مکث می‌کند، حالا این به ما بستگی دارد که آیا می‌خواهیم چیزی را تغییر دهیم، متغیرها را بررسی کنیم، یا اگر می‌خواهیم اسکریپت را تا اتمام اجرا کنیم. برای دستور اجرای کامل، دستور Continue را دوباره اجرا کنید. خروجی باید به صورت زیر باشد:

20
The program finished and will be restarted
> /Users/junaid/Desktop/calc.py(3)<module>()
-> operators = ( '+', '-', '*', '/' )

در خروجی بالا مشاهده می شود که برنامه دقیقاً از همان جایی که متوقف شده است ادامه می دهد، قسمت باقی مانده را اجرا می کند و سپس مجدداً راه اندازی می شود تا در صورت تمایل بتوانیم آن را بیشتر اشکال زدایی کنیم. اکنون به بخش بعدی می رویم.

یادداشت مهم: قبل از حرکت به جلو، با اجرای دستور “clear” و سپس تایپ کردن “y” در اعلان PDB، تمام نقاط شکست را پاک کنید.

توابع بعدی و مرحله ای

آخرین، اما نه کم اهمیت ترین، بیایید مطالعه کنیم next و step کارکرد؛ هنگامی که شما شروع به اشکال زدایی برنامه های خود می کنید از این موارد بسیار استفاده می شود، بنابراین بیایید یاد بگیریم که آنها چه کاری انجام می دهند و چگونه می توان آنها را پیاده سازی کرد.

را step و next توابع برای تکرار در سراسر کد ما خط به خط استفاده می شود. تفاوت بسیار کمی بین این دو وجود دارد در حین تکرار، اگر step تابع با یک فراخوانی تابع روبرو می شود، به خط اول تعریف آن تابع می رود و دقیقاً به ما نشان می دهد که در داخل تابع چه اتفاقی می افتد. در حالی که، اگر next تابع با یک فراخوانی تابع مواجه می شود، اجرا می شود همه خطوط آن تابع در یک حرکت و مکث در فراخوانی تابع بعدی.

سردرگم؟ بیایید آن را در یک مثال ببینیم.

با استفاده از دستور زیر برنامه را از طریق خط PDB اجرا کنید:

$ python -m pdb calc.py

حالا تایپ کنید continue در اعلان PDB، و این کار را تا زمانی که برنامه به پایان برسد ادامه دهید. من بخشی از کل توالی ورودی و خروجی را در زیر نشان خواهم داد که برای توضیح موضوع کافی است. دنباله کامل بسیار طولانی است و فقط شما را بیشتر گیج می کند، بنابراین حذف خواهد شد.

> /Users/junaid/Desktop/calc.py(1)<module>()
-> operators = ( '+', '-', '*', '/' )
(Pdb) step
> /Users/junaid/Desktop/calc.py(2)<module>()
-> numbers = ( 10, 20 )
.
.
.
.
> /Users/junaid/Desktop/calc.py(6)calculator()
-> print("Operators available: " )
(Pdb) step
Operators available:
> /Users/junaid/Desktop/calc.py(8)calculator()
-> for op in operators:
(Pdb) step
> /Users/junaid/Desktop/calc.py(10)calculator()
-> print(op)
(Pdb) step
+
> /Users/junaid/Desktop/calc.py(8)calculator()
-> for op in operators:
(Pdb) step
> /Users/junaid/Desktop/calc.py(10)calculator()
-> print(op)

.
.
.
.

اکنون کل برنامه را دوباره اجرا کنید، اما این بار به جای “step” از دستور “next” استفاده کنید. من ردیابی ورودی و خروجی را برای آن نیز نشان داده ام.

> /Users/junaid/Desktop/calc.py(3)<module>()
-> operators = ('+', '-', '*', '/')
(Pdb) next
> /Users/junaid/Desktop/calc.py(4)<module>()
-> numbers = (10, 20)
(Pdb) next
> /Users/junaid/Desktop/calc.py(6)<module>()
-> def calculator():
(Pdb) next
> /Users/junaid/Desktop/calc.py(15)<module>()
-> def main():
(Pdb) next
> /Users/junaid/Desktop/calc.py(18)<module>()
-> main()
(Pdb) next
Operators available:
+
-
*
/
Numbers to be used:
10
20
--Return--

بسیار خوب، اکنون که ما ردیابی خروجی برای هر دوی این توابع داریم، بیایید ببینیم که چگونه آنها متفاوت هستند. برای step تابع، شما می توانید ببینید که زمانی که calculator تابع نامیده می شود، حرکت می کند داخل آن تابع، و از طریق آن در “مرحله” تکرار می شود، و به ما نشان می دهد که در هر مرحله دقیقا چه اتفاقی می افتد.

با این حال، اگر ردیابی خروجی را مشاهده کنید next تابع، وقتی تابع “اصلی” فراخوانی می‌شود، به ما نشان نمی‌دهد که در داخل آن تابع چه اتفاقی می‌افتد (یعنی فراخوانی بعدی به تابع ماشین حساب)، و سپس مستقیماً نتیجه نهایی را در یک حرکت/گام چاپ می‌کند.

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

نتیجه

در این آموزش با یک تکنیک پیچیده برای اشکال زدایی آشنا شدیم python برنامه های کاربردی با استفاده از یک ماژول داخلی به نام PDB. ما به دستورات عیب‌یابی مختلفی که PDB در اختیار ما قرار می‌دهد، از جمله دستورات عیب‌یابی، وارد می‌شویم next و step عبارات، نقاط شکست، و غیره. ما همچنین آنها را در یک برنامه پایه اعمال کردیم تا آنها را در عمل ببینیم.

(برچسب‌ها به ترجمه)# python



منتشر شده در 1403-01-20 23:07:04

امتیاز شما به این مطلب
دیدگاه شما در خصوص مطلب چیست ؟

آدرس ایمیل شما منتشر نخواهد شد.

لطفا دیدگاه خود را با احترام به دیدگاه های دیگران و با توجه به محتوای مطلب درج کنید