آموزش پایتون - فراخوانی استثناها

فراخوانی استثناها (Exceptions) در پایتون

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

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

در پایتون، می‌توانید استثناهای توکار (Built-in) مانند ValueError یا TypeError را برای نشان دادن شرایط خطای رایج فراخوانی کنید. علاوه بر این، می‌توانید استثناهای سفارشی (Custom) خود را ایجاد و فراخوانی نمایید.

فراخوانی استثناهای توکار (Built-in)

شما می‌توانید هر استثنای توکاری را با ایجاد یک نمونه (Instance) از کلاس استثنا و استفاده از دستور raise فراخوانی کنید. سینتکس آن به شرح زیر است −

raise Exception("This is a general exception")

مثال

در ادامه مثالی آمده است که در آن وقتی یک آرگومان نامعتبر به تابع ارسال می‌شود، استثنای ValueError را فراخوانی می‌کنیم −

def divide(a, b):
   if b == 0:
      raise ValueError("Cannot divide by zero")
   return a / b

try:
   result = divide(10, 0)
except ValueError as e:
   print(e)

خروجی کد بالا به صورت زیر است −

Cannot divide by zero

فراخوانی استثناهای سفارشی (Custom Exceptions)

علاوه بر استثناهای توکار، می‌توانید با ایجاد یک کلاس استثنای جدید که از کلاس پایه Exception یا هر یک از زیرکلاس‌های آن ارث‌بری می‌کند، استثناهای سفارشی خود را تعریف و فراخوانی کنید −

class MyCustomError(Exception):
   pass

def risky_function():
   raise MyCustomError("Something went wrong in risky_function")

try:
   risky_function()
except MyCustomError as e:
   print(e)

خروجی کد بالا همان‌طور که در زیر نشان داده شده است می‌باشد −

Something went wrong in risky_function

ایجاد استثناهای سفارشی

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

برای ایجاد یک استثنای سفارشی در پایتون، کلاس جدیدی تعریف می‌کنید که از کلاس توکار Exception یا هر کلاس استثنای توکار مناسب دیگری ارث‌بری می‌کند. این کلاس استثنای سفارشی می‌تواند دارای ویژگی‌ها (Attributes) و متدهای اضافی باشد تا جزییات دقیق‌تری در مورد شرایط خطا ارائه دهد.

مثال

در این مثال −

  • ما یک کلاس استثنای سفارشی به نام "InvalidAgeError" تعریف می‌کنیم که از "Exception" ارث‌بری می‌کند.
  • متد __init__() استثنا را با سن نامعتبر و یک پیام خطای پیش‌فرض مقداردهی اولیه می‌کند.
  • تابع set_age() در صورتی که سن ارائه شده خارج از محدوده معتبر باشد، استثنای "InvalidAgeError" را فراخوانی می‌کند.
class InvalidAgeError(Exception):
   def __init__(self, age, message="Age must be between 18 and 100"):
      self.age = age
      self.message = message
      super().__init__(self.message)

def set_age(age):
   if age < 18 or age > 100:
      raise InvalidAgeError(age)
   print(f"Age is set to {age}")

try:
   set_age(150)
except InvalidAgeError as e:
   print(f"Invalid age: {e.age}. {e.message}")

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

Invalid age: 150. Age must be between 18 and 100

فراخوانی مجدد استثناها (Re-Raising Exceptions)

گاهی اوقات ممکن است لازم باشد یک استثنا را مدیریت (Catch) کنید، عملیات خاصی (مانند ثبت در لوگ، پاک‌سازی یا ارائه جزییات بیشتر) را انجام دهید و سپس همان استثنا را دوباره فراخوانی کنید تا در سطوح بالاتر پشته فراخوانی (Call Stack) مدیریت شود.

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

برای فراخوانی مجدد یک استثنا در پایتون، از دستور "raise" بدون مشخص کردن استثنا استفاده می‌کنید که آخرین استثنای فعال در حوزه (Scope) فعلی را دوباره فراخوانی می‌کند.

مثال

در مثال زیر −

  • تابع process_file() تلاش می‌کند یک فایل را باز کرده و بخواند.
  • اگر فایل پیدا نشود، پیام خطایی را چاپ کرده و استثنای "FileNotFoundError" را دوباره فراخوانی می‌کند.
  • سپس این استثنا در سطح بالاتری از پشته فراخوانی دریافت و مدیریت می‌شود.
def process_file(filename):
   try:
      with open(filename, "r") as file:
         data = file.read()
         # Process data
   except FileNotFoundError as e:
      print(f"File not found: {filename}")
    	# Re-raise the exception
      raise  

try:
   process_file("nonexistentfile.txt")
except FileNotFoundError as e:
   print("Handling the exception at a higher level")

پس از اجرای کد بالا، خروجی زیر را دریافت می‌کنیم −

File not found: nonexistentfile.txt
Handling the exception at a higher level

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