امکان نوشتن برنامههایی وجود دارد که استثناءهای انتخابی را مدیریت کنند. مثال زیر را ببینید که تا زمانی که یک عدد صحیح معتبر وارد شود از کاربر ورودی میخواهد، اما به کاربر اجازه میدهد برنامه را قطع کند (با استفاده از Control-C یا هرچه سیستمعامل پشتیبانی میکند).
>>> while True:
... try:
... x = int(input("Please enter a number: "))
... break
... except ValueError:
... print("Oops! That was no valid number. Try again...")
دستور try به شکل زیر عمل میکند:
try و except) اجرا میشود.try تمام میشود.except مطابقت داشته باشد، بند except اجرا شده و سپس اجرا بعد از بلوک try/except ادامه مییابد.except مطابقت نداشته باشد، به دستورات try بیرونی منتقل میشود؛ اگر مدیریتی یافت نشود، یک استثنای مدیریت نشده است و اجرا با پیام خطا متوقف میشود.یک دستور try میتواند بیش از یک بند except داشته باشد، برای مشخص کردن مدیریتکنندهها برای استثناءهای مختلف. حداکثر یک مدیریتکننده اجرا میشود. مدیریتکنندهها فقط استثناءهایی را مدیریت میکنند که در بند try متناظر رخ میدهند، نه در سایر مدیریتکنندههای همان دستور try. یک بند except میتواند چندین استثنا را نام ببرد:
... except RuntimeError, TypeError, NameError: ... pass
یک کلاس در بند except استثنائاتی را مطابقت میدهد که نمونههایی از خود کلاس یا یکی از کلاسهای مشتقشده آن هستند (نه بالعکس). به عنوان مثال، کد زیر B، C، D را به همان ترتیب چاپ میکند:
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
for cls in [B, C, D]:
try:
raise cls()
except D:
print("D")
except C:
print("C")
except B:
print("B")
توجه کنید اگر بندهای except برعکس شوند (با except B اول)، B, B, B چاپ میکرد -- اولین بند except مطابقدار فعال میشود.
وقتی استثنایی رخ دهد، ممکن است مقادیر مرتبطی داشته باشد، که به آرگومانهای استثنا نیز گفته میشود. حضور و انواع آرگومانها به نوع استثنا بستگی دارد.
بند except میتواند یک متغیر بعد از نام استثنا مشخص کند. متغیر به نمونه استثنا متصل میشود که معمولاً یک ویژگی args دارد که آرگومانها را ذخیره میکند. برای راحتی، انواع استثناء داخلی __str__() را برای چاپ تمام آرگومانها بدون دسترسی صریح به .args تعریف میکنند.
>>> try:
... raise Exception('spam', 'eggs')
... except Exception as inst:
... print(type(inst)) # نوع استثنا
... print(inst.args) # آرگومانهای ذخیره شده در .args
... print(inst) # __str__ اجازه میدهد آرگومانها مستقیماً چاپ شوند
... x, y = inst.args # بازپاکسازی آرگومانها
... print('x =', x)
... print('y =', y)
...
('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs
خروجی __str__() استثنا به عنوان بخش آخر پیام برای استثناءهای مدیریت نشده چاپ میشود.
BaseException کلاس پایه مشترک تمام استثناءها است. یکی از زیرکلاسهای آن، Exception، کلاس پایه تمام استثناءهای غیرکشنده است. استثنائاتی که زیرکلاس Exception نیستند معمولاً مدیریت نمیشوند، زیرا نشان میدهند برنامه باید خاتمه یابد. اینها شامل SystemExit هستند که توسط sys.exit() و KeyboardInterrupt که هنگامی که کاربر میخواهد برنامه را قطع کند ایجاد میشود.
Exception میتواند به عنوان wildcard استفاده شود که (تقریباً) همه چیز را بگیرد. با این حال، بهترین تمرین این است که تا حد ممکن در مورد انواع استثنائاتی که قصد مدیریتشان را داریم دقیق باشیم و به استثناءهای غیرمنتظره اجازه انتشار بدهیم.
رایجترین الگو برای مدیریت Exception چاپ یا ثبت استثنا و سپس بازایجاد آن است (اجازه دادن به فراخوانکننده برای مدیریت استثنا نیز):
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error:", err)
except ValueError:
print("Could not convert data to an integer.")
except Exception as err:
print(f"Unexpected {err=}, {type(err)=}")
raise
دستور try ... except یک بند else اختیاری دارد که وقتی حاضر باشد، باید بعد از تمام بندهای except بیاید. برای کدی که باید اجرا شود اگر بند try استثنایی ایجاد نکند مفید است:
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except OSError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
استفاده از بند else بهتر از اضافه کردن کد اضافی به بند try است زیرا از گرفتن تصادفی استثنایی که توسط کد محافظت شده توسط دستور try ... except ایجاد نشده جلوگیری میکند.
مدیریتکنندههای استثنا فقط استثنائاتی را که مستقیماً در بند try رخ میدهند مدیریت نمیکنند، بلکه آنهایی را که در توابعی که (حتی به طور غیرمستقیم) در بند try فراخوانی میشوند نیز مدیریت میکنند:
>>> def this_fails():
... x = 1/0
...
>>> try:
... this_fails()
... except ZeroDivisionError as err:
... print('Handling run-time error:', err)
...
Handling run-time error: division by zeroاین محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://docs.python.org/3/tutorial