
با آموزش حضوری و آنلاین مقدماتی تا پیشرفته پایتون , محبوبترین زبان برنامهنویسی دنیا در محیطی عملی کاربردی و پروژه محور وارد دنیای برنامه نویسی شوید
مشاهده بیشتر
اگه پایتون بلدی و میخوای وارد دنیای هوش مصنوعی بشی، این دوره مخصوص توئه! با آموزش پروژهمحور و همراهی اساتید حرفهای، یاد بگیر چطور از هوش مصنوعی تو زمینههایی مثل پزشکی، بورس و املاک استفاده کنی.
مشاهده بیشتر
اگه یادگیری ماشین بلدی و آمادهای وارد چالشهای حرفهای بشی، دوره یادگیری عمیق پروژهمحور برای توئه! طراحی شبکههای عصبی و کار روی پروژههای واقعی مثل تشخیص تصویر و پردازش زبان رو اینجا یاد میگیری.
مشاهده بیشتر
با این دوره، Django رو از پایه شروع کن و به یک حرفهای تبدیل شو! یاد بگیر چطور با معماری MVT، پایگاه داده و RESTful API کار کنی، پروژههای واقعی بسازی و آنها رو روی وب سرور مستقر کنی!
مشاهده بیشترمشخصات مقاله
مدیریت خطا در پایتون / Exception Handling
مدیریت خطا در پایتون / Exception Handling
پایتون دو امکان ویژه برای مدیریت خطاهای پیشبینی نشده در اپلیکیشن ها فراهم کرده و قابلیت های اشکال زدایی (debugging) پرکاربردی به آن ها اضافه می کند.
- Exception Handling: در آموزش حاضر به تشریح مدیریت خطاها و استثناها خواهیم پرداخت. در زیر لیستی از خطاهای استاندارد از در پایتون را مشاهده می کنید.
- Assertion ها: این مبحث در آموزش مربوطه ی خود مورد پوشش قرار می گیرد.
KeyError
EnvironmentError
کلاس پایه تمامی خطاهایی که خارج از محیط پایتون رخ می دهد.
IOError
به هنگام بروز خطاهای مربوط به سیستم عامل رخ می دهد
IndentationError
کلاس پایه برای تمامی خطاهای ساختار نحوی (سینتکس) مربوطه توگذاری و indentation.
خطای جاری زمانی رخ می دهد که متد abstract که بایستی داخل کلاس به ارث برده شده پیاده سازی شده باشد، بدنه ی آن طبق انتظار تعریف و پیاده سازی نشده باشد.
به عبارت دیگر، این خطا را متدهای abstract که بدنه آن ها داخل کلاس های مشتق شده پیاده سازی نشده باشد، صدا زده می شود.
Assertion ها (دستورات assert و بررسی صحت شرط) در پایتون
assertion یک تست sanity-check یا تست ساده جهت بررسی معقولانه بودن ادامه ی فرایند تست می باشد. دستورات assert انتظار دارند که نتیجه ی عبارت صحیح باشد و مقدار true را برگرداند و چنانچه شرط برقرار نبود، یک خطا صادر می شود.
جهت درک آسان مفهوم assertion در پایتون، می توان آن را به دستور raise-if (یا به عبارت دقیق تر raise-if-not) تشبیه کرد. در این سناریو یک عبارت تست شده و صحت آن بررسی می شود. اگر نتیجه غلط بوده و خروجی مورد انتظار تولید نشد، یک خطا صادر می شود.
برای اجرای تست های assertion در اپلیکیشن، کافی است از دستورات assert استفاده نمایید. این کلیدواژه از ویرایش 1.5 به بعد زبان پایتون برای برنامه نویس قابل استفاده می باشد.برنامه نویسان معمولا دستورات assert را در ابتدای یک تابع قرار داده تا معتبر یا مجاز بودن ورودی را بررسی کند و نیز یک دستور assert دیگر جهت بررسی صحت خروجی تابع فراخوانی شده (در انتها و پس از صدا زدن تابع)، درج می کنند.
دستور assert
زمانی که پایتون در حین خواندن و تفسیر کد با دستور assert مواجه می شود، مفسر آن عبارت همراه را بررسی کرده که طبق انتظار باید صحیح باشد. اگر عبارت false بود، پایتون خطای AssertionError را صادر می کند.
نحوه ی استفاده از assert در زیر نمایش داده شده است:
1 | assert Expression[, Arguments]< button ></ button > |
اگر نتیجه ی expression یا عبارتی که پس از دستور assert درج می شود false بود (assertion ناموفق بود)، پایتون ArgumentExpression را به عنوان پارامتر برای AssertionError مورد استفاده قرار می دهد. خطاهای AssertionError را می توان به راحتی با استفاده از دستور try-except مدیریت کرد. اما اگر آن را مدیریت نکرده باشید، سبب می شوند برنامه خاتمه یافته و یک traceback (بازتاب مجموعه خطاهای تولید شده که به صورت پشته بر روی هم قرار گرفته اند) تولید شود.
مثالدر زیر تابعی را مشاهده می کنید که دما را از مقیاس کلوین به فارنهایت تبدیل می کند. از آنجایی که 0 درجه کلوین سردترین نقطه است، تابع اگر با مقدار منفی مواجه شود، خطا می دهد.
1 2 3 4 5 6 7 8 | #!/usr/bin/python def KelvinToFahrenheit(Temperature): assert (Temperature >= 0),"Colder than absolute zero!" return ((Temperature-273)*1.8)+32 print KelvinToFahrenheit(273) print int(KelvinToFahrenheit(505.78)) print KelvinToFahrenheit(-5) < button ></ button > |
کد بالا پس از اجرا، نتیجه ی زیر را بدست می دهد:
1 2 3 4 5 6 7 8 9 | 32.0 451 Traceback (most recent call last): File "test.py" , line 9 , in print KelvinToFahrenheit(- 5 ) File "test.py" , line 4 , in KelvinToFahrenheit assert (Temperature >= 0 ), "Colder than absolute zero!" AssertionError: Colder than absolute zero! <button></button> |
Exception (خطای زمان اجرا و پیشبینی نشده) چیست؟
Exception یک رخداد (event) است که در طول اجرا برنامه رخ می دهد و روند اجرای برنامه را مختل می نماید. در کل، زمانی که اسکریپت پایتون با شرایطی که قابلیت مدیریت آن را ندارد، مواجه می شود، یک خطا صادر می کند. exception در پایتون یک آبجکت پایتون است که نماینده ی خطا می باشد.
زمانی که اسکریپت پایتون یک خطا (exception) صادر می کند، یا باید خطا را مدیریت کند و یا برنامه را به طور کلی ببندد.
مدیریت Exception (خطا)
در صورت مواجه با کد مشکوک که ممکن است سبب رخداد خطا شود، می توانید آن را داخل بدنه ی try: قرار دهید. پس از بدنه ی try:، یک دستور except: در متن برنامه درج کرده و به دنبال آن قطعه کدی که مشکل برنامه را به صورت بهینه اداره می کند، تایپ نمایید.
نحوه ی استفاده از دستور
در زیر نحوه ی بکار بردن دستور try …except … else را مشاهده می کنید:
در زیر نکات آموزشی مهمی در خصوص ساختار فوق عنوان شده است:
- یک دستور try واحد می تواند چندین دستور متناظر except داشته باشد. این ویژگی به خصوص زمانی مفید واقع می شود که بدنه ی try حامل دستورات متعددی باشد که ممکن است هر یک خطای متفاوتی را سبب شود.
- می توانید یک عبارت except سراسری (generic) تنظیم کنید که هر خطایی را به راحتی مدیریت نماید.
- می توانید پس از دستور یا دستورات except، عبارت else را مورد استفاده قرار دهید. چنانچه کد موجود در بدنه ی try: خطا نداد، آنگاه قطعه کد else اجرا می شود.
- قطعه کد else جای مناسبی برای تعریف کدهایی می باشد که احتمالا مشکلی برای کل برنامه ایجاد نکرده و اجرای بدون خطای آن حتمی است.
کد زیر سعی دارد ابتدا یک فایل را باز کند و سپس در آن اطلاعاتی را درج نماید. از آنجایی مجوز در سطح نوشتن و درج داده های جدید داخل فایل اعطا نشده، خطای مربوطه توسط قطعه کد except صادر می شود.
1 2 3 4 5 6 7 8 9 | #!/usr/bin/python try: fh = open("testfile", "r") fh.write("This is my test file for exception handling!!") except IOError: print "Error: can\'t find file or read data" else: print "Written content in the file successfully" < button ></ button > |
کد بالا خروجی زیر را ارائه می دهد:
1 | Error: can't find file or read data<button></button> |
عبارت except بدون مشخص کردن نوع خطا
می توانید از دستور except که هیچ خطا یا exception ای در آن تعریف نشده نیز به صورت زیر استفاده نمایید و در واقع چنانچه هر گونه خطایی وجود داشت، دستور موجود در قطعه کد except را انجام دهد:
1 2 3 4 5 6 7 8 9 10 11 12 | try: You do your operations here; ...................... سعی کن یک عملیاتی را در اینجا انجام دهی except: If there is any exception, then execute this block. در صورت برخورد با خطا، عملیات دیگری را انجام بده ...................... else: If there is no exception then execute this block. در غیر این صورت این کار را انجام بده < button ></ button > |
این نوع دستور try-except تمامی خطاهایی که در برنامه رخ می دهد را گرفته و مدیریت می نماید. با این حال استفاده از این تکنیک در برنامه نویسی به هیچ وجه توصیه نمی شود چرا که تمامی خطاها را اداره می کند اما در ریشه یابی خطا و شناسایی اصل مشکل هیچ کمکی به توسعه دهنده نمی کند.
عبارت except با چندین Exception
می توانید با یک دستور except همزمان چندین exception را به صورت زیر مدیریت نمایید:
1 2 3 4 5 6 7 8 9 10 11 12 13 | try: You do your operations here; عملیاتی را در این قطعه کد امتحان نمایید ...................... except(Exception1[, Exception2[,...ExceptionN]]]): If there is any exception from the given exception list, then execute this block. در صورت مواجه شدن با خطا، کارهای تعریف شده در این بخش را اجرا نمایید ...................... else: If there is no exception then execute this block. اگر خطایی نبود، دستورات این بخش را اجرا کن < button ></ button > |
استفاده از ساختمان try-finally جهت مدیریت خطا
می توانید در انتهای قطعه کد try: از finally: نیز استفاده نمایید. دستوری که در بدنه ی finally: قرار می گیرد، صرف نظر اینکه خطایی در قطعه ی try رخ داده یا خیر، به طور قطع اجرا می شود. نحوه ی استفاده از این ساختار در زیر نمایش داده شده است:
1 2 3 4 5 6 7 8 9 10 11 | try: You do your operations here; عملیات را در اینجا انجام دهید ...................... Due to any exception, this may be skipped. ممکن است به دلیل وجود هر گونه خطایی این کد اجرا نشود finally: This would always be executed. دستوری که حتما اجرا خواهد شد ...................... < button ></ button > |
نمی توانید عبارت else و finally را یکجا بکار ببرید.
مثال1 2 3 4 5 6 7 | #!/usr/bin/python try: fh = open("testfile", "w") fh.write("This is my test file for exception handling!!") finally: print "Error: can\'t find file or read data" < button ></ button > |
اگر مجوز باز کردن فایل در سطح درج اطلاعات در آن را نداشته باشید، در آن صورت نتیجه ی زیر حاصل می گردد:
1 | Error: can't find file or read data< button ></ button > |
مثال فوق را می توان به صورت کارا و مختصرتر نیز، همچون نمونه کد زیر، نوشت:
1 2 3 4 5 6 7 8 9 10 11 | #!/usr/bin/python try: fh = open("testfile", "w") try: fh.write("This is my test file for exception handling!!") finally: print "Going to close the file" fh.close() except IOError: print "Error: can\'t find file or read data" < button ></ button > |
زمانی که سیستم در بدنه ی try با مشکل مواجه شده و خطای مربوطه را صادر کرد، اجرا سریعا به قطعه کد finally انتقال می یابد. پس از اینکه کلیه ی دستورات موجود در بدنه ی finally اجرا شدند، خطای مزبور بار دیگر رخ داده، ولی این بار در لایه ی بالاتر دستور try-except بعدی، به واسطه ی دستورات except مدیریت می شود.
آرگومان ارسال شده به Exception
یک exception می تواند آرگومان (argument) نیز داشته باشد. آرگومان پاس داده شده به exception، اطلاعات بیشتری را درباره ی خطای رخ داده ارائه می دهد. محتوای آرگومان می تواند با توجه به نوع خطا متفاوت باشد. می توانید با لحاظ کردن یک متغیر ساده در عبارت except، مانند زیر، آرگومانی را به exception ارسال نمایید:
1 2 3 4 5 6 | try: You do your operations here; ...................... except ExceptionType, Argument: You can print value of Argument here... < button ></ button > |
اگر کدی بنویسید که تنها یک خطا (exception) را مدیریت کند، در آن صورت کافی است یک متغیر پس از اسم خطا، در دستور except، لحاظ نمایید. چنانچه لازم است چندین خطا را گیر انداخته و مدیریت نمایید، در آن صورت می توانید متغیری پس از چندتایی exception خطا (متغیر exception از نوع چندتایی یا tuple) لحاظ نمایید.
این متغیر مقدار خطا که یک رشته باشد را گرفته و در واقع دلیل بروز خطا را در خود ذخیره می کند. این متغیر می تواند یک مقدار را دریافت کند یا همزمان چندین مقدار را در قالب یک چندتایی (tuple) در خود نگه دارد. این متغیر چندتایی (از نوع tuple) اغلب حامل رشته ی متنی خطا، شماره ی خطا و محل رخداد آن می باشد.
مثالمثال زیر تنها یک خطا را مدیریت می کند.
1 2 3 4 5 6 7 8 9 10 | #!/usr/bin/python # Define a function here. def temp_convert(var): try: return int(var) except ValueError, Argument: print "The argument does not contain numbers\n", Argument # Call above function here. temp_convert("xyz"); < button ></ button > |
نتیجه ی زیر را بدست می دهد:
1 2 3 | The argument does not contain numbers invalid literal for int () with base 10 : 'xyz' <button></button> |
تعریف و مدیریت خطا با استفاده از دستور raise
می توانید با استفاده از دستور raise خطاهای متعددی را مدیریت کنید. سینتکس و ساختار نحوی کلی برای مدیریت خطا با استفاده از دستور raise در زیر نمایش داده شده است.
ساختارکلی و نحوه ی استفاده از raise
1 | raise [Exception [, args [, traceback]]]< button ></ button > |
در اینجا، پارامتر Exception در واقع نوع خطا (برای مثال NameError) و پارامتر argument یک مقدار است که به آرگومان exception یا خطا ارسال می شود. پارامتر argument کاملا اختیاری است و در صورت عدم ارسال مقداری به آن، آرگومان مزبور برابر None خواهد بود.
آخرین آرگومان، traceback، نیز اختیاری است و در واقع به ندرت مورد استفاده قرار می گیرد. این آرگومان پشته ای از خطاها و یک آبجکت traceback هست که مربوط به خطای مورد نظر می باشد.
مثالexception می تواند یک رشته، کلاس و یا آبجکت باشد. اغلب خطاهایی که Python core صادر می کند از جنس کلاس هستند و یک آرگومان نیز دارند که نمونه ای از آن کلاس می باشد. تعریف خطاهای جدید امری بسیار آسان است و به راحتی زیر قابل پیاده سازی می باشد:
1 2 3 4 5 6 | def functionName( level ): if level < 1: raise "Invalid level!", level # The code below to this would not be executed # if we raise the exception <button></ button > |
جهت گرفتن و مدیریت خطا، عبارت "except" بایستی به همان خطایی که آبجکت، کلاس یا رشته ی ساده صادر کرده، اشاره کند. برای مثال، جهت گرفتن و ضبط خطای فوق، لازم است دستور except را به صورت زیر تنظیم نمایید:
1 2 3 4 5 6 7 | try: Business Logic here... except "Invalid level!": Exception handling here... else: Rest of the code here... < button ></ button > |
خطاهای اختصاصی و user-defined
پایتون به توسعه دهنده این امکان را می دهد تا خطاهای دلخواه خود را تعریف کند. برای این منظور می بایست از کلاس های درون ساخته ی exception ارث بری نماید.
در زیر مثالی را مشاهده می کنید که در آن یک خطای زمان اجرا و مربوط به RuntimeError رخ داده است. در مثال حاضر، یک کلاس تعریف شده که این کلاس خود از کلاس پایه ی RuntimeError مشتق (subclass) شده است. چنانچه لازم است اطلاعات بیشتری در خصوص خطای رخ داده برای کاربر نمایش دهید، توصیه می شود از این روش استفاده نمایید.
در بدنه ی دستور try: خطاهای اختصاصی (user-defined exception) تعریف (raise) شده و سپس این خطا داخل ساختمان except ضبط و مدیریت (catch) می شود. متغیر e در واقع یک آبجکت یا نمونه ای ساخته شده از روی کلاس Networkerror می باشد.
1 2 3 4 | class Networkerror(RuntimeError): def __init__(self, arg): self.args = arg < button ></ button > |
زمانی که کلاس فوق را تعریف کردید، آنگاه می توانید خطا را به صورت زیر اعلان و پیاده سازی کنید:
1 2 3 4 5 | try: raise Networkerror("Bad hostname") except Networkerror,e: print e.args < button ></ button > |