6. الاستثناءات
سنلقي الآن نظرة على الاستثناءات.
![]() |
يوضح البرنامج النصي الأول الحاجة إلى معالجة الاستثناءات.
نقوم بإحداث خطأ عن قصد لرؤية المعلومات التي ينتجها المترجم. النتيجة هي كما يلي:
السطر 4 يعطينا:
- نوع الاستثناء: ZeroDivisionError؛
- رسالة الخطأ المرتبطة: قسمة عدد صحيح أو معادلة على صفر. وهي باللغة الإنجليزية. قد ترغب في تغيير ذلك.
القاعدة الأساسية في البرمجة هي أننا يجب أن نبذل كل ما في وسعنا لتجنب الأعطال "غير المتحكم فيها" مثل تلك المذكورة أعلاه. حتى في حالة حدوث خطأ، يجب أن ينتهي البرنامج بشكل صحيح من خلال تقديم معلومات حول الخطأ الذي حدث.
صيغة معالجة الاستثناءات هي كما يلي:
try:
actions susceptibles de lancer une exception
except [classe d'exception, ...]:
actions de gestion de l'exception
finally:
actions toujours exécutées qu'il y ait exception ou non
في كتلة try، يتوقف تنفيذ الإجراءات فور حدوث استثناء. في هذه الحالة، يستمر التنفيذ مع الإجراءات الموجودة في جملة except.
الـ
except [MyException, ...]:
يعترض الاستثناءات من النوع MyException أو الأنواع المشتقة. عندما يحدث استثناء في كتلة try، يفحص المترجم جمل except المرتبطة بكتلة try بالترتيب الذي كُتبت به. ويتوقف عند أول جملة except قادرة على معالجة الاستثناء الذي حدث. إذا لم يجد أي منها، يتم تمرير الاستثناء مرة أخرى إلى الطريقة المستدعية. إذا كانت تلك الطريقة تحتوي على كتلة try/except، يتم معالجة الاستثناء مرة أخرى؛ وإلا، يستمر في الانتقال لأعلى سلسلة الطرق المستدعاة. في النهاية، يصل إلى مترجم Python. ثم يقوم المترجم بإنهاء البرنامج قيد التشغيل وعرض رسالة خطأ من النوع الموضح في المثال السابق. وبالتالي، فإن القاعدة هي أن البرنامج الرئيسي يجب أن يلتقط جميع الاستثناءات التي قد تنتقل من الطرق المستدعاة.
يحمل الاستثناء معلومات حول الخطأ الذي حدث. يمكن استرداد هذه المعلومات باستخدام الصيغة التالية:
except MyException as informations:
information عبارة عن مجموعة تحتوي على المعلومات المتعلقة بالاستثناء.
الصيغة
except MyException, erreur:
تقوم بتعيين رسالة الخطأ المرتبطة بالاستثناء إلى المتغير error.
لإلقاء استثناء، استخدم الصيغة
raise MyException(param1, param2, ...)
حيث تكون MyException في الغالب فئة مشتقة من فئة Exception. وستكون المعلمات التي تم تمريرها إلى منشئ الفئة متاحة لعبارة except في هياكل معالجة الاستثناءات.
يتم توضيح هذه المفاهيم من خلال البرنامج النصي التالي.
يعالج البرنامج النصي التالي الأخطاء بشكل صريح:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | |
ملاحظات:
- الأسطر 6–9: التعامل مع القسمة على الصفر؛
- السطر 8: نلتقط الاستثناء الذي حدث بالضبط؛
- السطر 11: بسبب الاستثناء الذي حدث، لم يتلق x أي قيمة وبالتالي لم يتغير؛
- الأسطر 15-19: نقوم بنفس الشيء ولكننا نلتقط استثناءً أعلى مستوى من النوع Exception. نظرًا لأن استثناء ZeroDivisionError مشتق من فئة Exception، فإن جملة except ستلتقطه؛
- الأسطر 23–33: ندرج عدة جمل except لمعالجة أنواع متعددة من الاستثناءات. سيتم تنفيذ جملة except واحدة فقط، أو لن يتم تنفيذ أي منها إذا لم يتطابق الاستثناء مع أي جملة except؛
- الأسطر 51–55: قد لا تحتوي جملة except على أي حجج. في هذه الحالة، تلتقط جميع الاستثناءات؛
- الأسطر 59–62: نقدم استثناء ValueError؛
- الأسطر 66–69: استرداد المعلومات التي يحملها الاستثناء؛
- الأسطر 73–76: تشرح كيفية إثارة استثناء؛
- الأسطر 79–84: توضح استخدام فئة استثناء مخصصة، MyError؛
- السطور 79–80: فئة MyError ترث ببساطة من فئة Exception الأساسية. وهي لا تضيف أي شيء إلى فئتها الأساسية. ولكن الآن، يمكن تسميتها صراحةً في جمل except؛
- الأسطر 97–107: توضح أنه في Python، يمكنك فعليًا إثارة أي نوع من الكائنات، وليس فقط الكائنات المشتقة من فئة Exception؛
- الأسطر 109–127: توضح استخدام جملة finally.
إخراج الشاشة كما يلي:
0 : integer division or modulo by zero
x=2
1 : integer division or modulo by zero
2 : (Exception) integer division or modulo by zero
3 : (ZeroDivisionError) integer division or modulo by zero
4 : il y a eu un probleme
5 : invalid literal for int() with base 10: 'x'
6 : invalid literal for int() with base 10: 'x'
7 : ('param1', 'param2', 'param3')
8 : ('info1', 'info2', 'info3')
9 : mon msg d'erreur
10 : pb...
11 : finally x=1
12 : exception
12 : finally x=None
يوضح هذا البرنامج النصي الجديد كيفية انتقال الاستثناءات عبر سلسلة طرق الاستدعاء:
ملاحظات:
- الأسطر 27–30: في الاستدعاء main --> f1 --> f2 --> f3 (السطر 28)، ستنتقل استثناء MyError الذي أطلقته f3 إلى main. ثم سيتم التعامل معها بواسطة جملة except في السطر 29؛
- الأسطر 55–58: في الاستدعاء main → f4 → f5 → f6 (السطر 56)، سينتقل استثناء MyError الذي أطلقته f6 إلى main. ثم سيتم التعامل معه بواسطة جملة except في السطر 29. هذه المرة، أثناء انتقاله عبر سلسلة طرق الاستدعاء، يتم إثراء استثناء MyError بالمعلومات التي تضيفها كل طريقة على طول الطريق.
يكون إخراج الشاشة كما يلي:
