خطاهای نحو (Syntax Errors) اصلی ترین خطاهایی هستند که به دلیل اشتباه و عدم رعایت درست نحو زبان برنامه نویسی رخ می دهند. زمانی که پایتون به خطی برسد که نتواند آنرا درک کند، خطای نحوی یا SyntaxError رخ می دهد. با بروز خطای نحوی، اجرای برنامه در نقطه ای که خطا رخ داده است متوقف خواهد شد. قطعه کد ۱ نمونه مثالی را نشان می دهد که چون علامت : در انتهای شرط حلقه while قرار نداده شده است، خطای نحو رخ داده است. به خطاهای نحو، Parsing Error نیز گفته می شود. از خروجی فایل و محلی (خطی) که خطا در آن رخ داده شده است، مشخص می شود.

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

استثناها

حتی اگر نحو عبارت if درست و بدون مشکل نحو باشد، بازهم ممکن است زمانی که برنامه را اجرا می کنید، خطایی رخ دهد. خطاهایی که در حین اجرای برنامه رخ می دهند را استثنا (Exception) می گویند و بر خلاف خطاهای نحوی، استثناها قابل اداره شدن هستند. برخی از خطاهایی که رخ می دهند شامل تقسیم بر صفر (Divided by Zero)، متغیری که تعریف نشده و می خواهیم از آن استفاده کنیم یا جمع یک مقدار عددی با مقدار رشته ای از خطاهایی هستند که جز خطاهای نحوی یا منطقی نیستند.

در قطعه کد ۲ سه نوع استثنا بسته به نوع خطا نشان داده شده است. ZeroDivisionError زمانی رخ می دهد که مقدار عددی را بر عدد صفر تقسیم می کنیم. منظور از تقسیم یکی از عملگرهای / و % است. NameError زمانی رخ می دهد که از نام متغیری استفاده کرده ایم که قبلا تعریف نشده است. TypeError زمانی رخ می دهد که یک تابع یا عملگر را بر روی نوع داده ها انجام دهیم که این تابع یا عملگر غیر معتبر باشد.

 بنابراین هر استثنا توسط یک نوع و متنی که در خروجی نشان داده می شود قابل شناسایی هستند. در لینک های زیر فهرست کاملی از استثناهای درونی پایتون (Built-in Exceptions) وجود دارد. در کنار اسثناهای پیشفرض و درونی خود پایتون، برنامه نویس ها نیز می توانند اسثناهای خودشان را تعریف کنند.

فهرست استثناهای درونی پایتون ۲

فهرست استثناهای درونی پایتون ۳

اداره کردن استثناها

 می توان برنامه ها را به گونه ای نوشت که استثناها را درون آن اداره کرد. در قطعه کد ۳ برنامه ای نوشته شده است که کاربر باید به عنوان ورودی عدد صحیح را وارد کند. در صورتی که کاربر عدد صحیح را وارد نکند، یک استثنا از نوع ValueError رخ می دهد.

در خط ۳ از طریق تابع ()input یک ورودی دریافت می کنیم. ماهیت تابع ()input به این صورت است که ورودی دریافتی را به صورت رشته ذخیره می کند و برای همین از تابع ()int برای تبدیل رشته عددی به عدد استفاده شده است. در پایتون برای کنترل و ادره کردن اسثناها از عبارت های try … except استفاده می کنیم. عبارت try به صورت زیر عمل می کند:

  • در ابتدا عبارت های میان عبارت try اجرا می شوند.
  • اگر هیچ استثنایی رخ ندهد، اجرای عبارت های بخش try به اتمام می رسد.
  • در جلوی عبارت except نام و نوع استثنا مشخص شده است. اگر در حین اجرای عبارت های try یک استثنا رخ دهد، روند اجرا از درون عبارت های try خارج می شود و اگر نوع استثنا رخ داده شده با نوع استثنا جلوی عبارت except یکسان باشد، عبارت درون بخش except اجرا خواهد شد. پس از این بقیه عبارت های پس از try … except اجرا می شوند.
  • اگر استثنایی که رخ می دهد با استثنایی که رخ می دهد مطابق با استثنای جلوی عبارت except نباشد، پایتون سعی می کند که اداره کردن این استثنا را به عبارت try داخلی (Outer) ارسال کند. اگر عبارت try داخلی وجود نداشت، این استثنا، یک استثنای اداره نشده (unhandled exception) خواهد بود و یک پیغام متناسب با این استثنا توسط خود پایتون چاپ می شود.

در قطعه کد ۳ تنها استثنای ValueError اداره می شود و اگر عددی غیر صفر بر عدد صفر تقسیم شود، استثنای ZeroDivisionError رخ می دهد که چون جلوی هیچ عبارت except نوشته نشده است، پس جز استثناهای اداره نشده قرار می گیرد و در صورت بروز این استثنا خطای زیر نشان داده می شود.

عبارت try می تواند بیش از یک بخش except داشته باشد. قطعه کد ۵ نمونه مثالی را نشان می دهد که بازنویسی شده قطعه کد ۳ است و در آن استثناهای ValueError و ZeroDivisionError اداره می شوند.

نمایش پیغام ها در زمان رخ دادن استثناها

در قطعه کدهای ۳ و ۵ خود برنامه نویس پیغامی را تعیین کرده است که در زمان رخ دادن استثنا باید نشان داده شود. مطابق قطعه کد ۲ و ۴ اگر برنامه نویس پیغامی را برای زمان بروز استثنا تعیین نکند، خود پایتون یک پیغام را نشان خواهد داد. مطابق قطعه کد ۶ می توان همین پیغام را درون یک متغیر (در اینجا متغیری به نام message) ذخیره کرد و سپس درون بدنه عبارت except آنرا نشان داد.

در خطوط ۶ و ۸ پیغام مربوط به استثنا درون متغیر message ذخیره می شود. نام استثنا و نام متغیر با ویرگول از هم جدا شده اند. البته می توان از کلمه as نیز به جای ویرگول استفاده کرد. همچنین می توان به جای اینکه چندین عبارت except را بنویسیم و در هر عبارت پیغام خطا را درون متغیر ذخیره کنیم، می توانیم دو یا چند استثنا را مطابق قطعه کد ۷ درون پرانتزهای باز و بسته قرار دهیم و سپس نام متغیر را پس از پرانتز بسته با ویرگول از آنها جدا کنیم.

ساختار try … except دارای بخش else نیز است. در قطعه کد ۸ از طریق ماژول sys چندین فایل از ورودی خوانده می شود. OSError استثنای اداره و کنترل شده است. در بخش try فایل ها باز می شود و اگر استثنا رخ دهد توسط OSError اداره می شود و در غیر این صورت در بخش else محتوای فایل نشان داده می شود.