تور آموزشی

مدیریت استثنا در پایتون

خطا و استثنا

موارد زیادی پیش می‌آید که یک خطا در برنامه رخ می‌دهد. بسیار مهم است که این خطا به درستی مدیریت شود و کاربر نهایی که از برنامه استفاده می‌کند با پیغام مناسب روبرو شود. خطاها در زبان پایتون دو حالت دارند. خطاهای نحوی یا نوشتاری (syntax error) و خطاهای منطقی (logical error). به خطای منطقی، استثنا (exception) گفته می‌شود.

خطای نحوی Syntax Error

خطاهای نحوی به خاطر رعایت نکردن روش درست استفاده از یک دستور ایجاد می‌شوند.

مثال:

if 200 > 100
    print(“200 is greater than 100”)

خروجی:

SyntaxError: invalid syntax

خطای بالا به خاطر ننوشتن کاراکتر دونقطه (:) در انتهای دستور if ایجاد شد.

استثنا Exception

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

مثال:

print(“result of division by zero: {}”.format(5/0))

خروجی:

ZeroDivisionError: division by zero

در مثال بالا هیچ خطای نحوی وجود ندارد. دستور print به درستی نوشته شده است و از متد format نیز به درستی استفاده شده است. اما تقسیم کردن عدد 5 بر عدد صفر از نظر ریاضی نادرست است. بنابراین با خطا روبرو می‌شویم. به چنین خطاهایی که در زمان اجرا با آن روبرو می‌شویم استثنا گفته می‌شود.

برای مدیریت استثنا در زبان پایتون از چهار بلوک کد استفاده می‌شود. این بلوک‌ها عبارت‌اند از:

بلوک try: در این بلوک کدهای اصلی برنامه که قرار است اجرا شوند و ممکن است دارای خطا باشند نوشته می‌شود.

بلوک except: از این بلوک برای مدیریت استثنا رخ داده استفاده می‌شود. به بیان دیگر اگر در بلوک try یک استثنا رخ دهد کدهای نوشته‌شده در این بلوک اجرا می‌شوند.

بلوک else: زمانی که هیچ خطایی رخ نمی‌دهد می‌توانیم در این بلوک کدهایی را اجرا کنیم.

بلوک finally: بدون توجه به اینکه در بلوک try یک استثنا صادر شده است یا نه و اینکه آیا این استثنا در بلوک except مدیریت شده است یا نه کدهای این بلوک اجرا می‌شوند.

استفاده از هر چهار بخش الزامی نیست. به طور معمول از بلوک‌های try و except استفاده می‌شود.

مثال:

try:
    a = b + 2
    print(“No Error”)
except:
    print(“Error!!!”)

خروجی:

Error!!!

با توجه به اینکه متغیر b بدون اینکه مقدار دهی شده باشد در محاسبات استفاده شده است پس در بلوک try خطا خواهیم داشت. بنابراین ادامه اجرای کد در بلوک try متوقف می‌شود و کدهای بلوک except اجرا می‌شود. در صورتی که این استثنا را مدیریت نمی‌کردیم با این خطا روبرو می‌شدیم:

NameError: name 'b' is not defined

مثال:

try:
    print(“Salam Python”)
except:
    print(“Error!!!”)
else:
    print(“No Error”)

خروجی:

Salam Python
No Error

در مثال بالا کد بلوک try بدون اشکال اجرا می‌شود. به همین دلیل بلوک except اجرا نمی‌شود ولی کد بلوک else اجرا می‌شود.

مثال:

try:
    a = b + 2
    print(a)
except:
    print(“Error!!!”)
finally:
    print(“Salam Python”)

خروجی:

Error!!!
Salam Python

در مثال بالا با توجه به خطای رخ داده در بلوک try (عدم مقداردهی متغیر b) وارد بلوک except خواهیم شد. همچنین بلوک finally نیز در هر حالت اجرا خواهد شد.

انواع استثنا

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

ZeroDivisionError

این استثنا زمانی رخ می‌دهد که یک عدد را بر صفر تقسیم کنیم.

NameError

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

TypeError

زمانی رخ می‌دهد که نوع داده ورودی به یک تابع اشتباه باشد. مثلا به یک تابع ریاضی مانند رادیکال (sqrt) به جای عدد، رشته بدهیم. یا دو نوع داده متفاوت با هم ترکیب شوند. مثلا یک متغییر عددی را با یک رشته جمع کنیم.

ValueError

زمانی رخ می‌دهد که نوع داده ورودی به تابع صحیح باشد ولی مقدار آن اشتباه باشد. مثلا به تابع رادیکال عدد منفی بدهیم.

IndexError

اگر یک لیست یا هر دنباله قابل پیمایش داشته باشیم و اندیسی را فراخوانی کنیم که وجود نداشته باشد این خطا رخ خواهد داد.

چند بلوک استثنا

از آنجایی که ممکن است در بلوک try خطاهای متفاوتی رخ دهد پایتون این امکان را به برنامه‌نویس می‌دهد که از چند بلوک except به صورت متوالی استفاده کند. احتمال رخ دادن این اتفاق زمانی بیشتر می‌شود که بعضی از داده‌هایی که در پردازش شرکت دارند توسط یک کاربر وارد شده باشند. زیرا در این حالت کاربر ممکن است داده‌های اشتباهی را وارد کرده باشد. در مثال زیر یک عدد از کاربر دریافت می‌کنیم سپس تلاش می‌کنیم رادیکال آن عدد را با توان 2 آن عدد جمع کنیم و آن را چاپ کنیم.

مثال:

import math
x = input(“Enter a number”)
try:
    print(math.sqrt(x) + math.pow(x, 2))
except TypeError:
    print(“The input variable is not a number”)
except ValueError:
    print(“The input variable is negative”)
except:
    print(“Unknown Error!”)

raise کردن یک استثنا

گاهی اوقات ممکن است نخواهیم از بلوک try استفاده کنیم. در این حالت با استفاده از کلمه کلیدی raise می‌توانیم یک استثنا ایجاد کنیم. به این کار raise کردن می‌گویند.

مثال:

x = -1
if x < 0:
          raise Exception(“the number have to be positive!”)

خروجی:

Exception: the number have to be positive!

لازم به ذکر است که Exception کلاس پایه (والد) برای سایر استثناهاست. زمانی که نوع استثنا را نمی‌دانیم می‌توانیم از این کلاس استفاده کنیم. همین مثال را می‌توان با ValueError بازنویسی کرد.

raise ValueError(“the number have to be positive!”)