عندما تبدأ في كتابة برامج بايثون، ستواجه حتماً مواقف يتوقف فيها البرنامج فجأة عن العمل ويعرض رسالة خطأ. هذه هي "الاستثناءات" (Exceptions). في هذا الدرس، سنتعلم ما هي الأخطاء والاستثناءات، ولماذا تحدث، وكيف نتعامل معها بذكاء لجعل برامجنا أكثر قوة واستقراراً.
تخيل أنك تبني تطبيقاً لإدارة المهام (Tasks API) كما سنفعل لاحقاً في هذه السلسلة. ماذا سيحدث إذا حاول المستخدم حذف مهمة غير موجودة؟ أو إذا أدخل نصاً بدلاً من رقم؟ بدون معالجة الأخطاء، سيتوقف التطبيق بالكامل ويعرض رسالة خطأ غير مفهومة للمستخدم. معالجة الأخطاء تسمح لنا بالتحكم في هذه المواقف وتقديم رسائل مفيدة بدلاً من تعطل البرنامج.
هناك نوعان رئيسيان من الأخطاء:
دعنا نرى بعض الاستثناءات التي ستواجهها كثيراً:
# ZeroDivisionError: القسمة على صفر
result = 10 / 0 # سيتوقف البرنامج هنا
# ValueError: قيمة غير صالحة
number = int("abc") # لا يمكن تحويل "abc" إلى رقم
# FileNotFoundError: ملف غير موجود
file = open("non_existent.txt", "r") # الملف غير موجود
# IndexError: مؤشر خارج نطاق القائمة
my_list = [1, 2, 3]
print(my_list[5]) # القائمة تحتوي فقط على 3 عناصر
# KeyError: مفتاح غير موجود في القاموس
my_dict = {"name": "Ahmed"}
print(my_dict["age"]) # المفتاح "age" غير موجود
لحسن الحظ، توفر بايثون أدوات قوية للتعامل مع الاستثناءات باستخدام try و except.
try:
# الكود الذي قد يسبب خطأ
number = int(input("أدخل رقماً: "))
result = 10 / number
print(f"النتيجة: {result}")
except ZeroDivisionError:
# ماذا تفعل إذا حدث خطأ القسمة على صفر
print("خطأ: لا يمكن القسمة على صفر!")
except ValueError:
# ماذا تفعل إذا أدخل المستخدم نصاً بدلاً من رقم
print("خطأ: يرجى إدخال رقم صحيح")
يمكنك استخدام except بدون تحديد نوع الخطأ، لكن هذا ليس أفضل ممارسة لأنه يخفي جميع الأخطاء:
try:
number = int(input("أدخل رقماً: "))
result = 10 / number
except:
print("حدث خطأ ما!") # لا نعرف نوع الخطأ بالضبط
else ينفذ إذا لم يحدث أي خطأ، و finally ينفذ دائماً بغض النظر عن حدوث خطأ:
try:
file = open("data.txt", "r")
content = file.read()
except FileNotFoundError:
print("الملف غير موجود. سيتم إنشاؤه.")
file = open("data.txt", "w")
file.write("محتوى افتراضي")
else:
print("تم قراءة الملف بنجاح!")
print(content)
finally:
file.close()
print("تم إغلاق الملف")
لنطبق ما تعلمناه في مثال عملي:
def simple_calculator():
print("آلة حاسبة بسيطة")
print("العمليات المتاحة: +, -, *, /")
try:
num1 = float(input("أدخل الرقم الأول: "))
operation = input("أدخل العملية (+, -, *, /): ")
num2 = float(input("أدخل الرقم الثاني: "))
if operation == "+":
result = num1 + num2
elif operation == "-":
result = num1 - num2
elif operation == "*":
result = num1 * num2
elif operation == "/":
if num2 == 0:
raise ZeroDivisionError("لا يمكن القسمة على صفر!")
result = num1 / num2
else:
print("عملية غير معروفة!")
return
print(f"النتيجة: {num1} {operation} {num2} = {result}")
except ValueError:
print("خطأ: يرجى إدخال أرقام صحيحة")
except ZeroDivisionError as e:
print(f"خطأ رياضي: {e}")
except Exception as e:
print(f"حدث خطأ غير متوقع: {e}")
finally:
print("شكراً لاستخدام الآلة الحاسبة")
# تشغيل التطبيق
simple_calculator()
أحياناً تحتاج إلى إنشاء استثناءات خاصة بك عندما يحدث موقف غير متوقع في منطق برنامجك:
def validate_age(age):
if age < 0:
raise ValueError("العمر لا يمكن أن يكون سالباً!")
if age > 150:
raise ValueError("العمر كبير جداً!")
return f"العمر {age} صحيح"
try:
print(validate_age(-5))
except ValueError as e:
print(f"خطأ في التحقق: {e}")
pass داخل except دون معالجة.قم بكتابة برنامج يطلب من المستخدم إدخال اسم ملف، ثم يحاول قراءة محتواه. استخدم معالجة الأخطاء للتعامل مع الحالات التالية:
حاول كتابة الحل بنفسك قبل النظر إلى الإجابة أدناه:
def read_file_safely():
while True:
filename = input("أدخل اسم الملف: ")
try:
file = open(filename, "r")
content = file.read()
print("محتوى الملف:")
print(content)
break # خروج من الحلقة إذا نجحت القراءة
except FileNotFoundError:
print(f"الملف '{filename}' غير موجود. حاول مرة أخرى.")
except IOError:
print(f"حدث خطأ في قراءة الملف '{filename}'.")
finally:
try:
file.close()
except NameError:
pass # الملف لم يفتح أصلاً
read_file_safely()
بهذا نكون قد تعلمنا أساسيات معالجة الأخطاء والاستثناءات في بايثون. تذكر أن البرنامج الجيد ليس الذي لا يحدث فيه أخطاء، بل الذي يتعامل مع الأخطاء بذكاء ويستمر في العمل. في الدرس القادم، سننتقل إلى موضوع مهم آخر: البرمجة الكائنية (OOP) التي ستساعدنا في تنظيم مشاريعنا الكبيرة.
جاري تحميل التقييمات...