الخطأ المتوقع
الخطأ (Error) إعلامٌ بوصول البرنامج لمسار مسدود. ويقع في أحد الإجراءات، ويؤدي إلى إيقاف البرنامج.
ويسمى الاستثناء (Exception) في لغات كثيرة؛ لكن ليس لنُدرته، ولا لقلة أهميَّته؛ بل هو مما يجب على المبرمج توقُّعه وبرمجة تتمته ليعود البرنامج لمساره الطبيعي دائمًا.
كيف تفهم تقرير الخطأ في البرمجة؟
ورسالته تتكون من ثلاثة أمور:
- نوع الخطأ: في السطر الأخير، قبل النقطتين
- كومة الاستدعاءات (Stack Trace): بعد سطر البداية وقبل السطر الأخير؛ تسردُ الاستدعاءات من الأقدم إلى الأحدث، حتى نصل إلى الدالَّة التي ترفع الخطأ.
- رسالة الخطأ: في السطر الأخير، بعد النقطتين
كومة الاستدعاءات
هي سلسلة الاستدعاءات التي قادت إلى الخطأ، من الأقدم إلى الأحدث.
كيف يتم رفع الخطأ؟
نستعمل الكلمة المفتاحية raise لرفع الخطأ، مع تحديد نوع الخطأ ورسالته، على هذا النحو:
الحالة الأولى: عدد سالب لا يقبله الجذر التربيعي:
الحالة الثانية: أننا لم نستورد المكتبة math، أصلاً:
كيف نتعامل مع الخطأ؟
يكون تعاملنا معه بإحدى طريقين:
- الاحتراز (
if): توقُّع حالات الخطأ والتحقق من عدمها قبل الإقدام على العملية. - الاستجابة (
try-except): ترك العملية لترجع بالخطأ؛ ثم نتعامل معه بحسبه.
وفيما يلي نسرد أكثر الأخطاء حدوثًا وكيفية التعامل معها..
أنواع الاستثناءات وأسبابها
لكل نوع حالات متعددة. مثلًا، يظهر TypeError عند جمع نوعين غير متوافقين، ويظهر أيضًا عند نسيان عامل مطلوب في استدعاء دالة. لذلك نقرأ الرسالة مع النوع قبل اختيار الحل.
هذه الحالات ليست كلها أنواعًا مستقلة في Python؛ فقد تبقى تسمية الخطأ نفسها ويتغيّر التفصيل الذي يليها.
تم تعريف أنواع من الخطأ في بايثون متبوعة بكلمة Error (عُرفًا)، وذلك باعتبار حالات خطأ نمطية ومتكررة، كلها في شجرة الأخطاء تحت النوع BaseException.
خطأ الصياغة (SyntaxError)
السبب: خطأ نحوي في صياغة اللغة:
- كلمة غير صحيحة: خطأ في الإملاء
- في وضع كلمة صحيحة في غير سياقها
- محاذاة غير متسقة (
IndentationError)
مثال:
الحل: اقرأ رسالة الخطأ وستدلُّك على السبب والموضع الذي حصل فيه الخطأ.
خطأ النوع (TypeError)
السبب:
- طلب إجراء بعدد أكثر أو أقل من العوامل الواجبة (مثل:
len(1, 2)) - طلب عملية بعوامل لا تقبل أنواعها (مثل:
math.sqrt('nine')أو5 + '5')
الحل: إذا كانت المشكلة في النوع، افحصه بـtype()أوisinstance()وحوّله عند الحاجة. وإذا كانت في عوامل الاستدعاء، راجع تعريف الدالة ومرّر العوامل المطلوبة دون زيادة أو تكرار.
مثال:
ستجد الخلاصة في السطر الأخير:
- نوع الخطأ:
TypeError - التفصيل: نوع المعطيات لعملية الجمع (
+) غير متوافقة؛ وهي: العدد (int) والنص (str).
ولاحظ أنه ذكر نوع العدد (int) لأنه قبله في ترتيب الكتابة.
خطأ القيمة (ValueError)
السبب: أن يكون النوع صحيحًا (فلا يحصُل TypeError) لكن القيمة غير مقبولة.
- مثلاً: طلب إجراء بقيمة نوعها عددي لكنَّها سالبة وهو لا يقبل السالبة. نحو:
math.sqrt(-16)فالجذر التربيعي لا يقبل السالب.
الحل: الاحتراز بفحص مدى القيمة قبل تنفيذ الأمر. ففي هذا المثالif x >= 0نتأكَّد بها أولاً؛ فإن لم تكن القيمة صحيحة فإننا سندور في الحلقة حتى تكون القيمة في مدى ما يمكن أن تعالجه دالةmath.sqrtثم ننهي الحلقة بـbreakهكذا:
خطأ السِّمة وخطأ الاسم (AttributeError & NameError)
NameError: لا تجد Python الاسم في النطاق الحالي؛ قد لا يكون عُرّف بعد، أو قد يكون محليًا داخل دالة أخرى. راجع الاسم وترتيب التنفيذ ونطاقه، واستعمل القيمة المُرجعة من الدالة إذا احتجتها خارجها.AttributeError: الكائن موجود، لكن السمة أو الطريقة المطلوبة غير متاحة عليه (مثل:a.x). راجع اسم السمة ونوع الكائن.