|
36 | 36 | مقدمه |
37 | 37 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
38 | 38 |
|
39 | | -بروز **خطا (Error)** همواره جزیی از برنامهنویسی بوده و هست. خطاهای برنامهنویسی انواع گوناگونی دارند؛ «خطاهای زمان کامپایل» (Compile-time errors) که آنقدر فاحش هستند که مانع از اجرای برنامه خواهند شد و برخی دیگر که میتوانند آنقدر ناقلا باشند که تا مدتها پس از اجرا نیز خودشان را نشان ندهند! به این دسته از خطاها به اصطلاح «خطاهای زمان اجرا» (Runtime errors) میگویند. |
| 39 | +بروز **خطا (Error)** همواره جزیی از برنامهنویسی بوده و هست. خطاهای برنامهنویسی انواع گوناگونی دارند؛ «خطاهای زمان کامپایل» (Compile-time errors) که آنقدر فاحش هستند که مانع از ترجمه کدهای برنامه به زبان ماشین و در نهایت اجرای آن خواهند شد و برخی دیگر که میتوانند آنقدر ناقلا باشند که تا مدتها پس از اجرا نیز خودشان را نشان ندهند! به این دسته از خطاها به اصطلاح «خطاهای زمان اجرا» (Runtime errors) میگویند. |
40 | 40 |
|
41 | | -**«خطاهای زمان کامپایل» (Compile-time errors)** حاصل اشتباه برنامهنویس بوده و معمولا نیز کشف و برطرف نمودن آنها نیز بسیار ساده میباشد و از عدم رعایت درست قواعد زبان برنامهنویسی مانند سینتکس نشات میگیرند. |
| 41 | +**«خطاهای زمان کامپایل» (Compile-time errors)** حاصل اشتباه فاحش برنامهنویس بوده و معمولا نیز کشف و برطرف نمودن آنها نیز بسیار ساده میباشد و از عدم رعایت درست قواعد زبان برنامهنویسی مانند سینتکس نشات میگیرند. |
42 | 42 |
|
43 | 43 | اما بروز **«خطاهای زمان اجرا» (Runtime errors)** میتواند به عوامل گوناگونی وابسته باشد همانند مشکلات سختافزاری که ناگهان به برنامه تحمیل میگردد که اگر از فرض این احتمال نیز صرف نظر کنیم!، باز هم برای دفاع در برابر این دسته از خطاها، برنامهنویس میبایست کاملا هوشیار باشد. به خصوص در زبانهای برنامهنویسی پویا به مانند پایتون که انواع داده در زمان اجرا تعیین میگردند. برای مثال فرض کنید در داخل یک تابع قرار است با یک نوع ``int`` کار شود ولی به علت ضعف برنامهنویسی و عدم کنترل ورودیها، یک داده با نوع ``str`` به آن ارسال گردد که در این صورت نتیجه مشخص است! البته جلوگیری از این دست خطاها نیز همچنان ساده میباشد!. گاهی ممکن است وضعیت آنچنان مهلک باشد که یا خیلی دیر به وجود یک خطا در برنامه پی ببریم یا برای کشف علت آن زمان زیادی صرف کنیم یا هر دو! به این نوع از خطاهای زمان اجرا، «خطاهای منطقی» (Logical errors) گفته میشود. |
44 | 44 |
|
|
59 | 59 |
|
60 | 60 | | |
61 | 61 |
|
62 | | -| |
63 | | -
|
64 | 62 | به زبان برنامهنویسی پایتون برمیگردیم. انواع خطاها در پایتون را میتوان در دو دسته کلی زیر در نظر گرفت: |
65 | 63 |
|
66 | | -* خطاهای سینتکس (Syntax errors) |
| 64 | +* خطای سینتکس (Syntax error) |
| 65 | + |
| 66 | +* خطای زمان اجرا (Runtime error) |
| 67 | + |
| 68 | +برای درک این دستهبندی و مطابقت دادن آن با توضیحات پیش لازم است تا بار دیگر به روند اجرای کدهای پایتون توجه نماییم (درس سوم - پشت صحنه اجرا). میدانیم پایتون یک زبان مفسری است، ولی پیش از اجرا، کدهای پایتون به یک زیان میانی به نام بایتکد (ByteCode) ترجمه یا کامپایل میشوند؛ در این مرحله قواعد پایتون بررسی و در صورتی که مشکل یا خطایی وجود نداشته باشد، بایتکد ایجاد و به اجرا در میآید. خطاهایی که در این مرحله (تلاش برای ترجمه و ایجاد بایتکد) ممکن است رخ دهند، **خطای سینتکس (Syntax error)** نامیده میشوند. |
| 69 | + |
| 70 | +زمانی که برنامه پایتونی به اجرا درمیآید، یعنی از نظر رعایت قوانین یا سینتکس مشکلی وجود نداشته است، بنابراین باقی خطاها در زمان اجرا رخ خواهند داد. در زبان برنامهنویسی پایتون تمام خطاهای زمان اجرا در قالب یک Exception اعلام یا به اصطلاح **raise** خواهند شد. |
| 71 | + |
| 72 | + |
| 73 | +ردیابی خطا در پایتون (Traceback) |
| 74 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 75 | + |
| 76 | +پس از وقوع یک خطا در زمان اجرای یک برنامه پایتونی، برای ردیابی و کشف علت رخ دادن آن خطا از Traceback استفاده میگردد. منظور از **Traceback**، گزارشی است که جهت راهنمایی برنامهنویس در هنگام وقوع یک خطای زمان اجرا، توسط مفسر پایتون ارائه داده میشود و گاهی نیز از آن به عنوان **Stack Trace** یاد میشود: |
| 77 | + |
| 78 | + |
| 79 | +.. code-block:: python |
| 80 | + :linenos: |
| 81 | + |
| 82 | + def sum_int(a, b): |
| 83 | + return a + b |
| 84 | + |
| 85 | + res = sum_int(2, 3) |
| 86 | + print(res) |
| 87 | +
|
| 88 | + res = sum_int(3, 'C') |
| 89 | + print(res) |
| 90 | +
|
| 91 | +:: |
| 92 | + |
| 93 | + 5 |
| 94 | + Traceback (most recent call last): |
| 95 | + File "sample.py", line 7, in <module> |
| 96 | + res = sum_int(3, 'C') |
| 97 | + File "sample.py", line 2, in sum_int |
| 98 | + return a + b |
| 99 | + TypeError: unsupported operand type(s) for +: 'int' and 'str' |
| 100 | + |
| 101 | +نمونه کد بالا نمایش مثالی از بروز خطا در زمان اجراست که پیشتر نیز به آن اشاره کردیم. در این مثال، یک اسکریپت با نام ``sample.py`` ایجاد کردهایم و کد بالا در آن درج گردیده است. تابع ``sum_int`` یک بار با مقدار قابل پذیریش (هر دو از نوع ``int``) فراخوانی میگردد (سطر ۴) و نتیجه (یعنی مقدار ``5``) نیز با موفقیت در خروجی چاپ میگردد (توسط دستور موجود در سطر ۵). اما در سطر هفتم، آرگومانهایی با نوع نامتناسب برای عملگر جمع ریاضی (``+``) ارسال میگردد و باعث بروز یک خطا یا اگر بهتر بگوییم، raise شدن یک Exception به نام ``TypeError`` میگردد. |
| 102 | + |
| 103 | +خروجی حاصل از وقوع Exception فوق نمایش Traceback در پایتون میباشد. Traceback پایتون یک راهنمایی کامل از نوع Exception و مراتب وقوع آن را به برنامهنویس گزارش میدهد که درک درست آن یک الزام برای برنامهنویسی میباشد. |
| 104 | + |
| 105 | +برخلاف برخی دیگر از زبانهای برنامهنویسی به مانند Java باید توجه داشت که Traceback پایتون را میبایست از پایین، یعنی سطر پایانی مورد بررسی قرار داد، این سطر توضیحی از نوع Exception رخ داده را ارائه میدهد و از این سطر به بالا مراحلی از روند اجرای برنامه که باعث بروز این Exception شده است را به ترتیب نمایش میدهد. ترتیب نمایش مراتب Exception نیز، از نمایش نقطه بروز Exception به قبل میباشد. به عنوان نمونه برای مثال قبل، میتوانیم مشاهده کنیم که گفته شده: |
| 106 | + |
| 107 | +* **نوع Exception چیست؟** Exception از نوع ``TypeError`` میباشد که در زمان استفاده از انواع نادرست از مقادیر برای عملگر ``+`` رخ داده است که در اینجا، این دو نوع عبارتند از: ``'int' and 'str'``. |
| 108 | + |
| 109 | +* **Exception در کجا رخ داده است؟** در سطر دوم از ``sample.py`` و داخل بدنه ``sum_int`` و هنگام اجرای دستور ``return a + b``. |
| 110 | + |
| 111 | +* **نقطه قبل از ورود به ناحیه Exception کجا بوده است؟** در سطر هفتم از ``sample.py`` و داخل حوزه ماژول، تابع ``sum_int`` با مقادیر ``3`` و ``'C'`` فراخوانی شده است: ``res = sum_int(3, 'C')``. |
| 112 | + |
| 113 | +* **آیا نقطه قبلتری نیز وجود دارد؟** خیر |
| 114 | + |
| 115 | +پایتون تا چندین سطح قبلتر از نقطه بروز Exception را توسط Traceback آشکار میکند. این امر کمک بسیاری در فهمیدن مسیر رسیدن به Exception را در اختیار برنامهنویس قرار میدهد. |
| 116 | + |
| 117 | +اکنون اجازه دهید نمونه کد مربوط به مثال قبل یعنی اسکریپت ``sample.py`` را با حفظ مشکل ``TypeError`` و افزودن کمی تغییر برای نمایش **خطای سینتکس (Syntax error)** آماده نماییم، بر همین اساس به نمونه کد زیر که حاوی دو خطا از نوع Syntax error میباشد و خروجی آن در زمان اجرا توجه نمایید: |
| 118 | + |
| 119 | +.. code-block:: python |
| 120 | + :linenos: |
| 121 | + |
| 122 | + def sum_int(a, b) |
| 123 | + return a + b |
| 124 | + |
| 125 | + res = sum_int(2, 3) |
| 126 | + print(res) |
| 127 | +
|
| 128 | + res = sum_int(3, 'C') |
| 129 | + print(res) |
| 130 | + |
| 131 | + |
| 132 | + " |
| 133 | +
|
| 134 | +:: |
| 135 | + |
| 136 | + File "sample.py", line 1 |
| 137 | + def sum_int(a, b) |
| 138 | + ^ |
| 139 | + SyntaxError: invalid syntax |
| 140 | + |
| 141 | +در نخستین بار اجرای اسکریپت ``sample.py``، پایتون متوجه یک خطای ``SyntaxError`` در سطر یکم میشود و جلوی مراحل تبدیل به بایتکد و در نهایت اجرای برنامه را در همان نقطه میگیرد. طبق توضیحات چاپ شده، خطا مربوط به عدم رعایت سینتکس درست برای تعریف تابع میباشد. کاراکتر ``^`` به جایگاه نادرست اشاره میکند. در انتهای تعریف سرآیند تابع اشکالی وجود دارد که با کمی دقت میتوان دریافت که علت به عدم وجود کاراکتر انتهایی سرآیند تابع در پایتون یعنی ``:`` میباشد. این مورد را اصلاح کرده و دوباره اقدام به اجرای اسکریپت ``sample.py`` مینماییم: |
| 142 | + |
| 143 | + |
| 144 | +.. code-block:: python |
| 145 | + :linenos: |
| 146 | + |
| 147 | + def sum_int(a, b): |
| 148 | + return a + b |
| 149 | + |
| 150 | + res = sum_int(2, 3) |
| 151 | + print(res) |
| 152 | +
|
| 153 | + res = sum_int(3, 'C') |
| 154 | + print(res) |
| 155 | + |
| 156 | + |
| 157 | + " |
67 | 158 |
|
68 | | -* خطاهای منطقی (Logical errors) |
| 159 | +:: |
69 | 160 |
|
70 | | -برای درک این دستهبندی و مطابقت دادن آن با توضیحات پیش لازم است تا بار دیگر به روند اجرای کدهای پایتون توجه نماییم (درس سوم - پشت صحنه اجرا). |
| 161 | + File "sample.py", line 11 |
| 162 | + " |
| 163 | + ^ |
| 164 | + SyntaxError: EOL while scanning string literal |
71 | 165 |
|
| 166 | +اینبار فرآیند اجرای برنامه در نقطهای دیگر متوقف میگردد، سطر یازدهم از ``sample.py``. این خطا نیز از نوع ``SyntaxError`` میباشد ولی با توضیحی متفاوت. متن خطا میگوید که نحوه قرار گرفتن کاراکتر ``"`` اشتباه است. سطر یازدهم با یک کاراکتر کوتیشن پایان یافته که جفت آن و نیز عبارت یا دستوری مرتبط با آن در سطر مذکور موجود نمیباشد. |
72 | 167 |
|
| 168 | +با اصلاح این مشکل، برنامه از حالت ``SyntaxError`` خارج شده و کد اسکریپت ``sample.py`` با موفقیت به بایتکد ترجمه و به اجرا درمیآید. اکنون در زمان اجرا، با ``TypeError`` که پیشتر بررسی کردیم برخورد خواهیم کرد! |
73 | 169 |
|
74 | 170 |
|
| 171 | +این نکته را نیز در نظر بگیرید - همانطور که اگر به خروجیهای دقت کرده باشید حتما متوجه شدهاید در دو حالت مربوط به گزارش خطای مربوط به ``SyntaxError`` خبری از سطر ``:Traceback (most recent call last)`` که در حالت خطای زمان اجرای ``TypeError`` مشاهده کردیم، نمیباشد. در واقع این سطر تنها در گزارش خطاهایی که پس از اجرای برنامه رخ دهند (Runtime errors)، نمایش داده خواهد شد. در زمان بررسی و ترجمه کد پایتون به بایتکد هرجا مشکلی باشد عملیات در همان نقطه متوقف میشود و صرفا گزارشی مبنی بر ابراز آن نقطه به برنامهنویس ارايه میگردد و نه چیزی که بتوان آن را یک گزارش ردیابی با Traceback نامید چرا که هنوز برنامه به اجرا درنیامده و اصلا نیازی به این کار نیست! |
75 | 172 |
|
76 | 173 |
|
77 | 174 |
|
|
0 commit comments