موارد استثنا در پایتون «Python Exception Handling» خطاهایی را که در طول اجرای برنامه رخ میدهند مدیریت میکند. موارد استثنا در پایتون این امکان را فراهم میکند که به خطا پاسخ داده شود به جای اینکه برنامه در حال اجرا متوقف شود. این ویژگی به شما این امکان را میدهد که خطاها را شناسایی و مدیریت کنید و کد شما را مقاومتر و کاربر پسندتر میسازد. در نتیجه تلاش برای تقسیم یک عدد بر صفر منجر به یک استثنا میشود.
مقدمه
در برنامهنویسی با پایتون، خطاها و موارد پیشبینینشده بخشی طبیعی از فرآیند اجرا هستند. برای مدیریت این موقعیتها، پایتون مکانیزمی قدرتمند و انعطافپذیر به نام موارد استثنا ارائه میدهد. موارد استثنا در پایتون به برنامهنویسان این امکان را میدهند که رفتار برنامه را در هنگام وقوع خطاها کنترل کنند و از توقف ناگهانی یا نتایج نادرست جلوگیری کنند.
این قابلیت نه تنها شامل استثناهای داخلی برای خطاهای رایج مانند تقسیم بر صفر یا دسترسی به اندیس نامعتبر است، بلکه امکان تعریف استثناهای سفارشی «Custom exceptions» را نیز فراهم میکند تا بتوان خطاهای خاص یک برنامه را به شکلی دقیقتر مدیریت کرد. در نتیجه، موارد استثنا در پایتون «Exception management» یکی از اصول مهم در نوشتن کدهای پایدار و حرفهای در پایتون محسوب میشود.
مثالی از استثنا: تلاش برای تقسیم یک عدد بر صفر باعث ایجاد استثنا میشود.
# Example of an exception n = 10 try: res = n / 0 # This will raise a ZeroDivisionError except ZeroDivisionError: print("Can't be divided by zero!")
خروجی:
Can't be divided by zero!
در این مثال، تقسیم یک عدد بر صفر باعث ایجاد خطای ZeroDivisionError میشود. بلوک try شامل کدی است که ممکن است باعث ایجاد استثنا شود و بلوک except استثنا را مدیریت کرده و به جای متوقف کردن برنامه، یک پیام خطا چاپ میکند.
تفاوت بین استثنا و خطا در پایتون
خطا (Error): خطاها مشکلات جدی هستند که برنامه نباید سعی کند آنها را مدیریت کند. این مشکلات معمولا در منطق یا پیکربندی کد وجود دارند و باید توسط برنامهنویس «Programmer» رفع شوند. مثالها شامل خطاهای نحوی «Syntax Errors» و خطاهای مربوط به حافظه است.
استثنا (Exception): استثناها کمتر از خطاها جدی هستند و برنامه میتواند آنها را مدیریت کند. این موارد به دلیل شرایطی مانند ورودی نامعتبر «Invalid input» ، فایلهای گمشده یا مشکلات شبکه به وجود میآیند.
# Syntax Error (Error) print("Hello world" # Missing closing parenthesis # ZeroDivisionError (Exception) n = 10 res = n / 0
یک خطای نحوی «Syntax Error» اشتباهی در کدنویسی است که مانع اجرای کد میشود. در مقابل، استثنایی مانند ZeroDivisionError را میتوان در حین اجرای برنامه با استفاده از مدیریت استثنا کنترل کرد.
نحو و کاربرد موارد استثنا در پایتون
مدیریت استثنا در پایتون با استفاده از بلوکهای try، except، else و finally انجام میشود.
try: # Code that might raise an exception except SomeException: # Code to handle the exception else: # Code to run if no exception occurs finally: # Code to run regardless of whether an exception occurs
بلوکهای try، except، else و finally در پایتون
بلوک try: بلوک try به ما اجازه میدهد یک بخش از کد را برای خطاها آزمایش کنیم. پایتون سعی میکند کد موجود در این بلوک را اجرا کند. اگر استثنایی رخ دهد، اجرا بلافاصله به بلوک except منتقل میشود.
بلوک except: بلوک except به ما امکان مدیریت خطا یا استثنا را میدهد. اگر کدی درون بلوک try خطا ایجاد کند، پایتون به بلوک except میرود و آن را اجرا میکند. میتوانیم استثناهای خاصی را مدیریت کنیم یا از یک except کلی برای گرفتن همه استثناها استفاده کنیم.
بلوک else: بلوک else اختیاری است و در صورت وجود، باید پس از تمام بلوکهای except قرار گیرد. این بلوک فقط در صورتی اجرا میشود که در بلوک try هیچ استثنایی رخ ندهد. این برای کدی که باید در صورت موفقیت بلوک try اجرا شود، مفید است.
بلوک finally: بلوک finally همیشه اجرا میشود، صرفنظر از اینکه استثنایی رخ داده باشد یا نه. این معمولا برای عملیات پاکسازی مانند بستن فایلها یا آزاد کردن منابع استفاده میشود.
مثال:
try: n = 0 res = 100 / n except ZeroDivisionError: print("You can't divide by zero!") except ValueError: print("Enter a valid number!") else: print("Result is", res) finally: print("Execution complete.")
خروجی:
You can't divide by zero! Execution complete.
- بلوک try از کاربر ورودی میگیرد و تلاش میکند عدد ۱۰۰ را بر عدد واردشده تقسیم کند.
- بلوکهای except خطاهای ZeroDivisionError و ValueError را مدیریت میکنند.
- بلوک else در صورتی اجرا میشود که هیچ استثنایی رخ ندهد و نتیجه را نمایش میدهد.
- بلوک finally بدون توجه به نتیجه اجرا میشود و نشاندهنده تکمیل اجرای برنامه است.
استثناهای رایج در پایتون
پایتون استثناهای داخلی «sInternal exception» بسیاری دارد که هرکدام نشاندهنده یک شرایط خطای خاص هستند. برخی از استثناهای رایج عبارتاند از:
توضیحات | نام استثنایی |
کلاس پایه برای همه استثناهای داخلی. | BaseException |
کلاس پایه برای همه استثناهای غیر خروجی. | Exception |
کلاس پایه برای تمام خطاهای مربوط به عملیات حسابی. | ArithmeticError |
زمانی که عملیات تقسیم یا مدول با صفر به عنوان مقسومکننده انجام میشود، افزایش مییابد. | ZeroDivisionError |
هنگامی که یک عملیات عددی از حداکثر محدودیت یک نوع داده تجاوز می کند، افزایش می یابد. | OverflowError |
هنگامی که عملیات ممیز شناور با شکست مواجه می شود، افزایش می یابد. | FloatingPointError |
هنگامی که یک عبارت assert با شکست مواجه می شود، مطرح می شود. | AssertionError |
هنگامی که یک مرجع یا تخصیص ناموفق باشد، افزایش می یابد. | AttributeError |
هنگامی که یک زیرنویس دنباله خارج از محدوده باشد، افزایش می یابد. | IndexError |
هنگامی که کلید فرهنگ لغت یافت نشد، افزایش می یابد. | KeyError |
هنگامی که حافظه یک عملیات تمام می شود، افزایش می یابد. | MemoryError |
زمانی که نام محلی یا جهانی پیدا نمی شود مطرح می شود. | NameError |
هنگامی که یک عملیات مربوط به سیستم (مانند فایل I/O) با شکست مواجه می شود، افزایش می یابد. | OSError |
هنگامی که یک عملیات یا عملکرد بر روی یک شی از نوع نامناسب اعمال می شود، افزایش می یابد. | TypeError |
هنگامی که یک تابع آرگومان از نوع مناسب اما مقدار نامناسب را دریافت می کند، افزایش می یابد. | ValueError |
زمانی مطرح می شود که بیانیه واردات دارای مشکلاتی باشد. | ImportError |
زمانی که یک ماژول پیدا نمی شود، افزایش می یابد. | ModuleNotFoundError |
گرفتن استثناها در پایتون
هنگام کار با موارد استثنا در پایتون، میتوانیم با مشخص کردن نوع استثناهایی که انتظار داریم، خطاها را بهطور موثرتری مدیریت کنیم. این کار میتواند کد را هم ایمنتر و هم راحتتر برای دیباگ کردن کند.
گرفتن استثناهای خاص در پایتون
گرفتن استثناهای خاص باعث میشود که کد بهطور متفاوتی به انواع موارد استثنا در پایتون پاسخ دهد.
try: x = int("str") # This will cause ValueError #inverse inv = 1 / x except ValueError: print("Not Valid!") except ZeroDivisionError: print("Zero has no inverse!")
خروجی:
Not Valid!
استثنای ValueError گرفته میشود زیرا رشته «str» نمیتواند به عدد صحیح تبدیل شود.
اگر x برابر با ۰ بود و تبدیل موفقیتآمیز میبود، خطای ZeroDivisionError در هنگام تلاش برای محاسبه معکوس آن گرفته میشد.
گرفتن چند استثنا در پایتون
ما میتوانیم چندین استثنا را در یک بلوک بگیریم اگر نیاز باشد که آنها را بهطور مشابه مدیریت کنیم یا میتوانیم آنها را جداگانه بگیریم اگر انواع مختلف استثناها نیاز به مدیریت متفاوتی داشته باشند.
a = ["10", "twenty", 30] # Mixed list of integers and strings try: total = int(a[0]) + int(a[1]) # 'twenty' cannot be converted to int except (ValueError, TypeError) as e: print("Error", e) except IndexError: print("Index out of range.")
خروجی:
Error invalid literal for int() with base 10: 'twenty'
خطای ValueError زمانی رخ میدهد که سعی میکنیم «بیست» را به یک عدد صحیح تبدیل کنیم.
خطای TypeError ممکن است زمانی رخ دهد که عمل بر روی انواع غیر صحیح به درستی اعمال نشود، اما در این تنظیم خاص، فعال نمیشود.
خطای IndexError زمانی به وقوع میپیوندد که به ایندکسی خارج از محدوده لیست دسترسی پیدا کنیم، اما در این سناریو، این موضوع تحت کنترل است.
مدیریت کننده های همگانی و خطرات آن ها در پایتون
در اینجا یک محاسبه ساده وجود دارد که ممکن است به دلایل مختلفی شکست بخورد.
try: # Simulate risky calculation: incorrect type operation res = "100" / 20 except ArithmeticError: print("Arithmetic problem.") except: print("Something went wrong!")
خروجی:
Something went wrong!
خطای ArithmeticError (بهطور خاص، مانند ZeroDivisionError) ممکن است در صورت مواجهه با خطای تقسیم عدد به عدد رخ دهد. با این حال، در اینجا خطای TypeError فعال میشود زیرا تلاش میشود یک رشته را بر عدد تقسیم کنیم.
استفاده از except: catch-all برای گرفتن TypeError است که نشاندهنده این خطر است که برنامهنویس ممکن است علت واقعی خطا (عدم تطابق نوع) را بدون ثبتنام دقیق خطا متوجه نشود.
ایجاد یک استثنا در پایتون
ما در پایتون با استفاده از کلمه کلیدی raise و به دنبال آن یک نمونه از کلاس استثنا که میخواهیم فعال کنیم، یک استثنا را ایجاد میکنیم. ما میتوانیم از استثناهای داخلی استفاده کنیم یا استثناهای سفارشی خود را با ارثبرداری از کلاس Exception داخلی پایتون تعریف کنیم.
نحو یا سینتکس پایه:
raise ExceptionType(“Error message”)
def set(age): if age < 0: raise ValueError("Age cannot be negative.") print(f"Age set to {age}") try: set(-5) except ValueError as e: print(e)
خروجی:
Age cannot be negative.
این تابع بررسی میکند که آیا مقدار سن منفی است یا خیر. اگر چنین باشد، یک استثنای ValueError با پیامی که مشکل را توضیح میدهد، ایجاد میکند.
این کار تضمین میکند که ویژگی سن نمیتواند به وضعیتی نامعتبر تنظیم شود و در نتیجه یکپارچگی دادهها حفظ میشود.
مزایای موارد استثنا در پایتون
- افزایش قابلیت اطمینان برنامه: با مدیریت مناسب استثناها، میتوان از کرش کردن برنامه یا تولید نتایج نادرست به دلیل خطاها یا ورودیهای غیرمنتظره جلوگیری کرد.
- سادهتر شدن مدیریت خطا: مدیریت استثناها به شما امکان میدهد کد مدیریت خطا را از منطق اصلی برنامه جدا کنید و خوانایی و نگهداری کد را آسانتر کنید.
- کد تمیزتر: با استفاده از مدیریت استثنا، میتوانید از شرطهای پیچیده برای بررسی خطاها اجتناب کرده و کدی تمیزتر و خواناتر ایجاد کنید.
- اشکالزدایی آسانتر: هنگامی که یک استثنا ایجاد میشود، مفسر پایتون یک traceback چاپ میکند که مکان دقیق وقوع استثنا را نشان میدهد و اشکالزدایی کد را آسانتر میکند.
معایب موارد استثنا در پایتون
- افزایش سربار عملکرد: مدیریت استثنا میتواند کندتر از استفاده از شرطها برای بررسی خطاها باشد، زیرا مفسر باید کار اضافی برای گرفتن و مدیریت استثنا انجام دهد.
- افزایش پیچیدگی کد: مدیریت استثنا میتواند کد را پیچیدهتر کند، بهویژه اگر نیاز به مدیریت انواع مختلف استثناها یا پیادهسازی منطق پیچیده خطا داشته باشید.
- خطرات امنیتی احتمالی: مدیریت نامناسب استثناها ممکن است اطلاعات حساس را فاش کرده یا آسیبپذیریهای امنیتی در کد شما ایجاد کند. بنابراین مهم است که استثناها با دقت مدیریت شوند و از افشای اطلاعات بیش از حد در مورد برنامه خودداری کنید.
نتیجه گیری
موارد استثنا در پایتون ابزاری قدرتمند برای مدیریت خطاها و اطمینان از اجرای صحیح برنامه هستند. با استفاده از استثناءهای داخلی و امکان تعریف استثناهای سفارشی، میتوان خطاهای خاص را به روشی مؤثر و قابلفهم مدیریت کرد. این قابلیت به توسعهدهندگان کمک میکند تا کنترل بهتری بر اجرای برنامه داشته باشند و از کرشهای ناگهانی جلوگیری کنند.
یکی از نکات کلیدی در مدیریت استثناءها، استفاده از بلوکهای try-except برای شناسایی و کنترل خطاهای رایج است. همچنین، در برخی موارد، نیاز به تعریف استثناءهای سفارشی برای موقعیتهای خاص برنامه احساس میشود. از طریق ارثبری از استثناءهای استاندارد میتوان منطق سفارشی ایجاد کرد و پیامهای خطای دقیقتری ارائه داد. این کار نهتنها باعث درک بهتر مشکلات میشود، بلکه به رفع سریعتر آنها کمک میکند. در نهایت، مدیریت صحیح استثناءها باعث افزایش پایداری برنامه و بهبود خوانایی کد خواهد شد.