في الدروس السابقة من سلسلة أساسيات بايثون تعلمنا كتابة الشروط، استخدام الحلقات، إنشاء الدوال، التعامل مع القوائم والقواميس، ثم تعلمنا في الدرس السابق كيفية قراءة وكتابة الملفات في Python.
لكن أثناء بناء البرامج العملية، ستقابل أخطاء كثيرة: المستخدم قد يكتب نصًا بدل رقم، أو يحاول البرنامج فتح ملف غير موجود، أو تحدث قسمة على صفر، أو تستخدم فهرسًا غير موجود داخل قائمة. لذلك يأتي هذا الدرس ليشرح لك مفهومًا مهمًا جدًا وهو التعامل مع الأخطاء Exceptions في Python.
في هذا الدرس ستتعلم كيف تستخدم try و except و else و finally بطريقة بسيطة، وكيف تختار نوع الخطأ المناسب بدل أن تخفي كل الأخطاء برسالة عامة لا تفيدك.
قبل أن تبدأ، يفضل أن تكون راجعت دروس كورس أساسيات بايثون، خصوصًا درس الشروط if و else في Python ودرس التعامل مع الملفات في Python لأن هذا الدرس مرتبط بهما بشكل مباشر.
الخلاصة السريعة: التعامل مع الأخطاء في بايثون لا يعني تجاهل الخطأ، بل يعني منع توقف البرنامج وعرض رسالة واضحة أو تنفيذ حل بديل عند حدوث مشكلة متوقعة. {alertInfo}
{getToc} $title={محتوى المقال}
ما المقصود بالأخطاء Exceptions في Python؟
الـ Exception هو خطأ يحدث أثناء تشغيل البرنامج. أحيانًا يكون الكود مكتوبًا بطريقة صحيحة من ناحية القواعد، لكن المشكلة تظهر أثناء التنفيذ بسبب قيمة غير مناسبة أو عملية غير مسموحة.
مثال بسيط:
number = 10
result = number / 0
print(result)
هذا الكود صحيح من حيث الكتابة، لكنه سيتوقف عند التشغيل لأن القسمة على صفر غير مسموحة:
ZeroDivisionError: division by zero
هنا لا نريد أن ينهار البرنامج بالكامل، بل نريد أن نقول للمستخدم مثلًا: لا يمكن القسمة على صفر.
الفرق بين SyntaxError و Exception
قبل أن نكمل، مهم جدًا أن تفرق بين نوعين من الأخطاء:
| النوع | متى يحدث؟ | مثال | هل try except تعالجه؟ |
|---|---|---|---|
SyntaxError |
عند وجود خطأ في قواعد كتابة الكود | نسيان النقطتين بعد if |
لا، يجب إصلاح الكود |
Exception |
عند حدوث مشكلة أثناء تشغيل الكود | القسمة على صفر أو فتح ملف غير موجود | نعم، يمكن التعامل معه غالبًا |
لو كان الخطأ بسبب نسيان النقطتين أو الأقواس أو علامات الاقتباس، فهذا خطأ في كتابة الكود نفسه. أما لو كان الخطأ بسبب قيمة أدخلها المستخدم أو ملف غير موجود، فهذا غالبًا خطأ أثناء التشغيل ويمكن التعامل معه باستخدام try except.
راجع أيضًا مقال حل خطأ SyntaxError invalid syntax في بايثون إذا كنت تريد فهم أخطاء الصياغة بشكل منفصل.
لماذا نحتاج إلى try و except؟
عندما تبني برنامجًا حقيقيًا، لا يمكنك ضمان أن كل شيء سيكون مثاليًا. المستخدم قد يكتب قيمة خاطئة، أو يحذف ملفًا يحتاجه البرنامج، أو يترك الإدخال فارغًا، أو يطلب عنصرًا غير موجود في قائمة.
استخدام try و except يساعدك على:
- منع توقف البرنامج بشكل مفاجئ.
- عرض رسالة مفهومة بدل رسالة خطأ طويلة.
- التعامل مع أخطاء إدخال المستخدم.
- التعامل مع أخطاء الملفات مثل
FileNotFoundError. - جعل البرنامج أكثر احترافية وأسهل للاستخدام.
الشكل الأساسي لاستخدام try و except
الصيغة الأساسية هي:
try:
# الكود الذي قد يسبب خطأ
except:
# الكود الذي يعمل إذا حدث خطأ
نضع داخل try الكود الذي قد يسبب خطأ، ونضع داخل except ما نريد تنفيذه عند حدوث الخطأ.
مثال بسيط: تحويل نص إلى رقم
من أشهر الأمثلة عند المبتدئين تحويل النص إلى رقم باستخدام int(). إذا كان النص يحتوي على رقم صحيح مثل "25"، سيعمل الكود بدون مشكلة:
age = int("25")
print(age)
لكن لو كانت القيمة:
age = int("abc")
print(age)
سيظهر خطأ:
ValueError: invalid literal for int() with base 10: 'abc'
لذلك نستخدم try except:
try:
age = int("abc")
print(age)
except:
print("من فضلك أدخل رقمًا صحيحًا")
بهذا الشكل لن يتوقف البرنامج، بل سيطبع رسالة واضحة.
هذا الخطأ شرحناه بتفصيل أكبر في مقال حل خطأ ValueError invalid literal for int في بايثون.
الأفضل: تحديد نوع الخطأ
رغم أن كتابة except وحدها تعمل، لكنها ليست أفضل ممارسة دائمًا، لأنها قد تخفي أخطاء أخرى لا تقصد التعامل معها.
الأفضل أن تحدد نوع الخطأ المتوقع:
try:
age = int("abc")
except ValueError:
print("القيمة المدخلة ليست رقمًا صحيحًا")
نصيحة مهمة: حاول دائمًا تحديد نوع الخطأ المتوقع مثلValueErrorأوZeroDivisionErrorأوFileNotFoundErrorبدل استخدامexceptعامة في كل الحالات. {alertSuccess}
مثال: التعامل مع خطأ القسمة على صفر
خطأ ZeroDivisionError يحدث عند محاولة القسمة على صفر.
try:
number = 10
result = number / 0
print(result)
except ZeroDivisionError:
print("لا يمكن القسمة على صفر")
الناتج:
لا يمكن القسمة على صفر
مثال عملي: برنامج قسمة رقمين
الآن لنكتب مثالًا أقرب للبرامج الحقيقية. البرنامج يطلب من المستخدم رقمين، ثم يقسم الرقم الأول على الثاني.
try:
num1 = float(input("أدخل الرقم الأول: "))
num2 = float(input("أدخل الرقم الثاني: "))
result = num1 / num2
print("النتيجة:", result)
except ValueError:
print("يجب إدخال أرقام فقط")
except ZeroDivisionError:
print("لا يمكن القسمة على صفر")
هذا المثال يتعامل مع حالتين:
- لو أدخل المستخدم نصًا بدل رقم، يظهر
ValueError. - لو كان الرقم الثاني صفرًا، يظهر
ZeroDivisionError.
استخدام except مع أكثر من نوع خطأ
يمكنك كتابة أكثر من except داخل نفس الكود، وكل واحدة تتعامل مع خطأ مختلف.
try:
numbers = [10, 20, 30]
print(numbers[5])
except IndexError:
print("الفهرس غير موجود داخل القائمة")
except TypeError:
print("هناك مشكلة في نوع البيانات")
بما أن القائمة تحتوي على 3 عناصر فقط، ومحاولة الوصول إلى الفهرس رقم 5 غير صحيحة، سيظهر:
الفهرس غير موجود داخل القائمة
راجع أيضًا مقال حل خطأ IndexError list index out of range في بايثون لفهم هذا الخطأ بشكل أوسع.
استخدام as لمعرفة رسالة الخطأ الأصلية
أحيانًا تريد أن تعرض رسالة الخطأ الأصلية التي أعطتها بايثون. يمكن فعل ذلك باستخدام as.
try:
age = int("abc")
except ValueError as error:
print("حدث خطأ:", error)
الناتج قد يكون:
حدث خطأ: invalid literal for int() with base 10: 'abc'
هذه الطريقة مفيدة أثناء التعلم، لأنها تساعدك على فهم سبب الخطأ الحقيقي بدل الاكتفاء برسالة عامة.
استخدام else مع try except
الجزء else يعمل فقط إذا لم يحدث أي خطأ داخل try.
try:
number = int("10")
except ValueError:
print("القيمة ليست رقمًا")
else:
print("تم التحويل بنجاح")
print(number)
الناتج:
تم التحويل بنجاح
10
استخدم else عندما تريد تنفيذ كود معين فقط في حالة نجاح الكود الموجود داخل try.
استخدام finally في Python
الجزء finally يعمل دائمًا، سواء حدث خطأ أو لم يحدث. يستخدم غالبًا لتنفيذ أوامر نهائية مثل إغلاق ملف، تنظيف موارد، أو طباعة رسالة انتهاء.
try:
number = int(input("أدخل رقمًا: "))
print("الرقم هو:", number)
except ValueError:
print("هذا ليس رقمًا صحيحًا")
finally:
print("انتهى تشغيل البرنامج")
سواء أدخل المستخدم رقمًا صحيحًا أو نصًا خاطئًا، سيتم تنفيذ السطر الموجود داخل finally.
مثال مهم: التعامل مع ملف غير موجود
بما أن الدرس السابق كان عن التعامل مع الملفات، فهذا المثال مهم جدًا. إذا حاولنا فتح ملف غير موجود، سيظهر خطأ FileNotFoundError.
try:
with open("data.txt", "r", encoding="utf-8") as file:
content = file.read()
print(content)
except FileNotFoundError:
print("لم يتم العثور على الملف، تأكد من اسم الملف والمسار")
هنا استخدمنا with حتى يتم إغلاق الملف تلقائيًا، واستخدمنا try except حتى لا يتوقف البرنامج إذا لم يكن الملف موجودًا.
ملاحظة مهمة: عند التعامل مع الملفات، لا يكفي أن تعرف open() فقط؛ يجب أن تتوقع أخطاء مثل عدم وجود الملف أو كتابة اسم الملف بشكل خاطئ. {alertInfo}
أشهر أنواع الأخطاء التي ستقابلها في بايثون
| نوع الخطأ | متى يحدث؟ | مثال بسيط | الحل المناسب |
|---|---|---|---|
ValueError |
عند استخدام قيمة غير مناسبة | int("abc") |
تحقق من القيمة أو استخدم try except |
ZeroDivisionError |
عند القسمة على صفر | 10 / 0 |
تحقق أن المقسوم عليه ليس صفرًا |
IndexError |
عند الوصول إلى فهرس غير موجود | items[10] |
تأكد من طول القائمة باستخدام len() |
KeyError |
عند استخدام مفتاح غير موجود في Dictionary | user["email"] |
استخدم get() أو تحقق من المفتاح |
FileNotFoundError |
عند محاولة فتح ملف غير موجود | open("data.txt") |
تأكد من اسم الملف أو تعامل مع الخطأ |
TypeError |
عند استخدام نوع بيانات بطريقة غير مناسبة | "5" + 3 |
صحح نوع البيانات قبل العملية |
مثال على KeyError في القواميس
في درس شرح Dictionaries في Python تعلمنا أن القاموس يخزن البيانات على شكل مفتاح وقيمة. إذا حاولت الوصول إلى مفتاح غير موجود، سيظهر خطأ KeyError.
user = {
"name": "Ali",
"age": 20
}
print(user["email"])
الحل باستخدام try except:
try:
print(user["email"])
except KeyError:
print("المفتاح المطلوب غير موجود")
لكن في القواميس، توجد طريقة أبسط في كثير من الحالات وهي استخدام get():
email = user.get("email", "لا يوجد بريد إلكتروني")
print(email)
متى تستخدم try except؟
استخدم try except عندما يكون الخطأ متوقعًا أثناء تشغيل البرنامج، مثل:
- إدخال المستخدم لقيمة غير صحيحة.
- فتح ملف قد لا يكون موجودًا.
- تحويل نص إلى رقم.
- التعامل مع بيانات خارجية قد تكون ناقصة.
- الوصول إلى عنصر قد لا يكون موجودًا في قائمة أو قاموس.
متى لا تستخدم try except؟
لا تستخدم try except لإخفاء أخطاء الكود التي يجب إصلاحها. مثلًا إذا كنت تكتب اسم المتغير بشكل خاطئ، فالحل ليس أن تخفي الخطأ، بل أن تصحح اسم المتغير.
| الحالة | هل نستخدم try except؟ | السبب |
|---|---|---|
| المستخدم قد يكتب نصًا بدل رقم | نعم | هذا خطأ متوقع من المستخدم |
| الملف قد لا يكون موجودًا | نعم | هذا احتمال طبيعي أثناء التشغيل |
نسيت نقطتين بعد if |
لا | هذا خطأ صياغة ويجب إصلاحه |
| كتبت اسم متغير خطأ | غالبًا لا | هذا خطأ في كتابة الكود ويجب تصحيحه |
تحذير مهم: لا تستخدم except: pass لإخفاء الأخطاء. هذا يجعل البرنامج يبدو وكأنه يعمل، لكنه يخفي مشكلة حقيقية قد تسبب أخطاء أكبر لاحقًا. {alertWarning}
خطأ شائع: استخدام except لإخفاء كل شيء
هذا مثال سيئ:
try:
number = int("abc")
except:
pass
المشكلة هنا أن الخطأ حدث فعلًا، لكنك أخفيته تمامًا. الأفضل أن تعرض رسالة مفهومة:
try:
number = int("abc")
except ValueError:
print("القيمة المدخلة يجب أن تكون رقمًا")
مثال تدريبي كامل للمبتدئين
هذا المثال يجمع بين try و except و else و finally. البرنامج يطلب من المستخدم إدخال عمره، ثم يطبع رسالة مناسبة.
try:
age = int(input("أدخل عمرك: "))
except ValueError:
print("يجب إدخال العمر كرقم صحيح")
else:
if age >= 18:
print("أنت بالغ")
else:
print("أنت أقل من 18 سنة")
finally:
print("شكرًا لاستخدام البرنامج")
هذا المثال يوضح:
try: محاولة تحويل الإدخال إلى رقم.except: التعامل مع الخطأ إذا أدخل المستخدم نصًا.else: تنفيذ كود عند نجاح التحويل.finally: تنفيذ رسالة النهاية في كل الحالات.
أفضل ممارسات التعامل مع الأخطاء في Python
- حدد نوع الخطأ بدل استخدام
exceptعامة. - اكتب رسالة واضحة للمستخدم.
- لا تخفِ الأخطاء باستخدام
passبدون سبب. - استخدم
withعند التعامل مع الملفات. - استخدم
elseعندما تريد تنفيذ كود فقط عند نجاحtry. - استخدم
finallyللأوامر التي يجب تنفيذها دائمًا. - لا تستخدم
try exceptكبديل عن فهم سبب الخطأ.
روابط داخلية مفيدة من بايثون العرب
- كورس أساسيات بايثون من الصفر
- أساسيات بايثون 11: شرح if و else في Python
- أساسيات بايثون 13: شرح Functions في Python
- أساسيات بايثون 18: شرح Dictionaries في Python
- أساسيات بايثون 22: شرح التعامل مع الملفات في Python
- مشكلة وحل: حل خطأ ValueError invalid literal for int
- مشكلة وحل: حل خطأ IndexError list index out of range
- بايثون بالمثال: معرفة هل الرقم زوجي أم فردي
- أفضل مشاريع بايثون للمبتدئين لتطبيق ما تعلمته
مصدر رسمي للتوسع
للمزيد من التفاصيل المتقدمة حول الأخطاء والاستثناءات في Python، يمكنك الرجوع إلى توثيق بايثون الرسمي: Errors and Exceptions - Python Documentation.
تمرين بسيط عليك
اكتب برنامجًا يطلب من المستخدم إدخال رقم، ثم يطبع مربع هذا الرقم. وإذا أدخل المستخدم نصًا بدل رقم، اطبع رسالة تقول:
من فضلك أدخل رقمًا صحيحًا
حاول حل التمرين بنفسك أولًا، ثم قارن فكرتك بهذا الحل:
try:
number = int(input("أدخل رقمًا: "))
square = number * number
print("مربع الرقم هو:", square)
except ValueError:
print("من فضلك أدخل رقمًا صحيحًا")
الخلاصة
في هذا الدرس تعلمت أن الأخطاء في بايثون جزء طبيعي من كتابة البرامج، وأن استخدام try و except يساعدك على التعامل مع الأخطاء المتوقعة بدل توقف البرنامج بشكل مفاجئ.
تعلمت أن try تحتوي على الكود الذي قد يسبب خطأ، وأن except تحتوي على الكود الذي يعمل عند حدوث الخطأ. وتعلمت أيضًا استخدام else عند نجاح الكود، و finally لتنفيذ أوامر نهائية في كل الحالات.
الأهم من ذلك: لا تستخدم التعامل مع الأخطاء لإخفاء المشاكل، بل استخدمه لجعل برنامجك أوضح وأكثر أمانًا واحترافية.
الخلاصة السريعة: استخدم try except مع الأخطاء المتوقعة مثل إدخال المستخدم والملفات، وحدد نوع الخطأ قدر الإمكان حتى يبقى الكود واضحًا وسهل الصيانة. {alertSuccess}
أسئلة شائعة مع إجاباتها
ما معنى Exception في Python؟
تعني خطأ يحدث أثناء تشغيل البرنامج، مثل القسمة على صفر، أو محاولة فتح ملف غير موجود، أو تحويل نص غير رقمي إلى رقم.
ما الفرق بين try و except؟
نضع داخل try الكود الذي قد يسبب خطأ، ونضع داخل except الكود الذي يتم تنفيذه إذا حدث هذا الخطأ.
ما فائدة else مع try except؟
الجزء else يعمل فقط إذا لم يحدث أي خطأ داخل try. لذلك نستخدمه عند وجود كود نريد تنفيذه بعد نجاح العملية.
ما فائدة finally؟
الجزء finally يعمل دائمًا، سواء حدث خطأ أو لم يحدث، ويستخدم غالبًا لتنفيذ أوامر نهائية مثل الإغلاق أو التنظيف.
هل يجب استخدام try except في كل برنامج؟
لا. استخدمها فقط عند وجود خطأ متوقع أثناء التشغيل، مثل إدخال المستخدم أو قراءة الملفات أو التعامل مع بيانات قد تكون غير صحيحة.
هل استخدام except العامة خطأ؟
ليست خطأ دائمًا، لكنها قد تخفي أخطاء مهمة. الأفضل غالبًا تحديد نوع الخطأ مثل ValueError أو FileNotFoundError.
ما الفرق بين SyntaxError و Exception؟
SyntaxError يحدث بسبب خطأ في كتابة قواعد الكود، مثل نسيان النقطتين. أما Exception فيحدث أثناء تشغيل البرنامج، مثل القسمة على صفر أو فتح ملف غير موجود.




