دستور try…except

می‌توان خطاها را با استفاده از دستور try…except اداره کرد. بدین صورت که کدی را که احتمال می‌دهید ایجاد خطا کند در داخل بلوک try قرار می‌دهید. بلوک except هم شامل کدهایی است که وقتی اجرا می‌شوند که برنامه با خطا مواجه شود. تعریف ساده‌ی این دو بلوک به این صورت است که بلوک try سعی می‌کند که دستورات را اجرا کند و اگر در بین دستورات خطایی وجود داشته باشد برنامه دستورات مربوط به بخش except را اجرا می‌کند. برنامه زیر نحوه استفاده از دستور try…except را نمایش می‌دهد :

  1: try:
  2:     result = 0;
  3:     x = 5;
  4:     y = 0;
  5: 
  6:     result = x / y; #ERROR 
  7:     
  8: except:
  9:     print("An attempt to divide by 0 was detected.");
An attempt to divide by 0 was detected.

در داخل بلوک try، مقدار x را که 5 است بر y که مقدار آن 0 است تقسیم کرده‌ایم. نتیجه محاسبه به وجود آمدن خطای ZeroDivisionError (عدد تقسیم بر صفر) است. از آنجاییکه در برنامه بالا خطایی به وجود آمده است کدهای داخل بلوک except اجرا می‌شوند. بنابراین :

try:
    result = x / y; #ERROR
    print("This line will not be executed.");
    
except:
    print("An attempt to divide by 0 was detected.");

می‌توانید از یک نوع استثناء مخصوص به یک خطا در داخل بلوک except استفاده کنید، مثلاً برای خطای تقسیم عدد بر صفر از ZeroDivisionError به شکل زیر استفاده کنید :

try:
    result = x / y; #ERROR 
    
except ZeroDivisionError:
    print("An attempt to divide by 0 was detected.");

همچنین می‌توانید اطلاعات مربوط به یک استثنا را با استفاده از کلمه کلیدی as در داخل یک متغیر قرار داده و سپس آن را نمایش دهید:

try:
    x = 5;
    y = 0;

    result = x / y; #ERROR 
    
except ZeroDivisionError as error:
    print(error);
division by zero

در کد بالا یک نمونه از کلاس ZeroDivisionError با استفاده از کلمه کلیدی as ایجاد کرده‌ایم (error). این نمونه شامل اطلاعاتی در مورد استثناء می باشد. همه کلاسهای استثناء توضیحاتی در مورد خطاها می‌دهند. در درسهای آینده در مورد خصوصیات استثناءها بیشتر توضیح می‌دهیم. اگر فکر می‌کنید که در بلوک try ممکن است با چندین خطا مواجه شوید می‌توانید از چندین بلوک except استفاده نمایید ولی به یاد داشته باشید که برای هر کدام از آن خطاها از کلاس استثناء مربوط به هر یک استفاده کنید.

try:
    x = 5;
    y = int(input("Please enter a number : "));
    result = x / y; #ERROR 
    
    print(result);

except ZeroDivisionError as error:
    print(error);
except ValueError as error:
    print(error);

از انجاییکه مقدار y به وسیله ورودی که از کاربر گرفته می‌شود، تعیین می‌شود، مقدار آن باید با توجه به مثال بالا غیر صفر باشد (عدد تقسیم بر صفر تعریف نشده است). اما یک مشکل وجود دارد. چون ممکن است که کاربر یک مقدار غیر عددی وارد کند (مثلاً یک حرف) که در این صورت برنامه نمی‌تواند حرف را به عدد تبدیل کند و خطای نوع (ValueError) اتفاق می افتد. وقتی استثناء اتفاق افتاد بلوک except مربوط به این خطا اجرا می‌شود و محاسبه خارج قسمت تقسیم x بر y نادیده گرفته می‌شود. کد بالا را به صورت خلاصه زیر هم می توان نوشت:

try:
    x = 5;
    y = int(input("Please enter a number : "));
    result = x / y;
    
    print(result);

except (ZeroDivisionError, ValueError) as error:
    print(error);

حال فرض کنید شما می‌خواهید تمام خطاهای احتمالی که ممکن است در داخل بلوک try اتفاق می افتند را فهمیده و اداره کنید این کار چگونه امکانپذیر است؟ به راحتی و با استفاده از کلاس عمومی Exception می‌توانید این کار را انجام داد. هر کلاس استثناء در پایتون از این کلاس ارث بری می‌کند بنابراین شما می‌توانید هر نوع استثناءیی را در شئی از کلاس Exception ذخیره نمایید.

try:
    #Put your codes to test here

except Exception as error:
    print(error);

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

try:

 #Put your codes to test here

except ZeroDivisionError as error:
    print(error);
except ValueError as error:
    print(error);
except Exception as error:
    print(error);

اگر کلاس پایه Exception را در اولین بلوک except قرار دهیم و خطایی در برنامه رخ دهد چون تمام کلاسهای استثناء از این کلاس مشتق می‌شوند در نتیجه اولین بلوک except اجرا شده و سایر بلوک‌ها حتی با وجود اینکه خطای مورد نظر به آنها مربوط باشد اجرا نمی‌شوند. شما می‌توانید از متد ()isinstance نیز به صورت زیر استفاده نمایید.

try:
    x = 5;
    y = int(input("Please enter a number : "));
    result = x / y;

except Exception as error:
    if isinstance(error, ZeroDivisionError):
        print("Cannot divide by zero!");
    if isinstance(error, ValueError):
        print("Format cannot be accepted!"); 

بلوک except از کلاس Exception برای به دام انداختن همه استثناءهایی که به وسیله برنامه به وجود می‌آید استفاده می‌کند. در داخل بلوک except می‌توانید با استفاده از یک دستور if و متد ()isinstance نوع استثناء به وجود آمده را بیابید. و به عنوان نکته آخر گاهی اوقات می خواهیم در صورتی که استثنائی رخ نداد یک پیغام هم به کاربر نمایش داده شود. این پیغام را هم می توان در داخل بخش try نوشت و هم می توان با استفاده از دستور else این کار را انجام داد:

try:
     x = 5;
     y = int(input("Please enter a number : "));
     result = x / y;

except:
     print("An attempt to divide by 0 was detected.");

else:                                
    print("Else statement reached.");

دستور else باید بعد از دستور except و قبل از دستور finally که در درس بعد توضیح می دهیم نوشته شود.