معالجة الاستثناءات

14.4 معالجة الاستثناءات

أهداف التعلم

في نهاية هذا القسم، ينبغي أن تكون قادرًا على

  • وصف استثنائين قد يحدثان عند قراءة الملفات.
  • كتابة تعليمات try/except التي تعالج الاستثناءات المُضمَّنة.

أخطاء وقت التشغيل

قد تحدث أخطاء متنوعة عند قراءة ملف:

  • FileNotFoundError: اسم الملف أو المسار غير صالح.
  • IndexError/ValueError: تنسيق الملف غير صالح.
  • أخطاء أخرى ناتجة عن محتويات ملف غير صالحة.

عند حدوث خطأ، يتوقف البرنامج ويعرض رسالة خطأ.

مثال 14.4

خطأ مطبعي في ملف

يحتوي ملف باسم food_order.txt على المحتويات التالية:

    5 sandwiches
    4 chips
    1 pickle
    soft drinks

يتوقع البرنامج التالي أن يبدأ كل سطر في الملف بعدد صحيح:

    for line in open("food_order.txt"):
        space = line.index(" ")
        qty = int(line[:space])
        item = line[space+1:-1]
        print(qty, item)

للأسف، السطر "soft drinks" لا يبدأ بعدد صحيح. ونتيجة لذلك، يتوقف البرنامج ويعرض رسالة خطأ:

    Traceback (most recent call last):
      File "food_order.py", line 3
        qty = int(line[:space])
    ValueError: invalid literal for int() with base 10: 'soft'

مفاهيم تطبيقية

الاستثناءات الشائعة

ما الخطأ الذي قد يحدث في كل موقف؟

1.
غُيِّر السطر "soft drinks" إلى "3-4 soft drinks".
  1. FileNotFoundError
  2. IndexError
  3. ValueError
2.
for line in open("food_order.text"):
  1. FileNotFoundError
  2. IndexError
  3. ValueError
3.
parts = line.split()
qty = parts[0]
item = parts[1]
  1. FileNotFoundError
  2. IndexError
  3. ValueError

استكشاف أعمق

تشرح صفحة الاستثناءات المُضمَّنة في مكتبة بايثون القياسية معنى كل استثناء.

تعليمتا try و except

يمكن تصميم البرامج لمعالجة الاستثناءات، بدلاً من إنهاء عملها. تُنفِّذ تعليمة try شِفرةً قد تُطلق استثناءً. وتُنفِّذ فقرة except شِفرةً استجابةً للاستثناء.

مثال 14.5

محاولة فتح ملف

يطلب البرنامج التالي، المسمى try_open.py، من المستخدم اسم ملف ويعد عدد الأسطر في الملف.

    name = input("Enter a filename: ")
    try:
        file = open(name)
        lines = file.readlines()
        count = len(lines)
        print(name, "has", count, "lines")
    except FileNotFoundError:
        print("File not found:", name)
    print("Have a nice day!")

عند تشغيل هذا البرنامج مع الإدخال try_open.py، وهو اسم ملف البرنامج، يكون الإخراج هو:

    Enter a filename: try_open.py
    try_open.py has 9 lines
    Have a nice day!

إذا لم يكن اسم الملف موجودًا، يُطلَق FileNotFoundError في السطر 3. ثم ينتقل البرنامج إلى فقرة except في السطر 7 ويستمر في العمل. يكون الإخراج الناتج هو:

    Enter a filename: try_open.txt
    File not found: try_open.txt
    Have a nice day!

مفاهيم تطبيقية

التنبؤ بالمخرجات مع الاستثناءات

لكل مقتطف شِفرة، ما هو الإخراج؟

4.
word = "one"
try:
  number = int(word)
  print(word, "equals", number)
except ValueError:
  print(word, "is not a number")
  1. one equals 1
  2. one is not a number
  3. ValueError: invalid literal for int() with base 10: 'one'
5.
word = "one"
try:
  number = int(word)
  print(word, "equals", number)
except IndexError:
  print(word, "is not a number")
  1. one equals 1
  2. one is not a number
  3. ValueError: invalid literal for int() with base 10: 'one'
6.
word = "one"
try:
  char = word[3]
  print("The char is", char)
except:
  print("That didn't work")
  1. The char is e
  2. That didn't work
  3. IndexError: string index out of range

جرّب بنفسك

محلل الأنواع

غالبًا ما تحتاج برامج التحليل إلى العثور على أرقام في كميات كبيرة من النصوص. كيف يمكن للبرنامج أن يحدد ما إذا كانت سلسلة نصية مثل "123.45" تمثل رقمًا؟ أحد الأساليب هو استخدام الاستثناءات:

  1. حاول تحويل السلسلة النصية إلى عدد صحيح. إذا لم يُطلَق ValueError، فإن السلسلة النصية تمثل عددًا صحيحًا.
  2. وإلا، حاول تحويل السلسلة النصية إلى عدد عشري. إذا لم يُطلَق ValueError، فإن السلسلة النصية تمثل عددًا عشريًا.
  3. وإلا، فإن السلسلة النصية لا تمثل رقمًا.

نفّذ الدالّة get_type() باستخدام هذا الأسلوب. تستدعي الكتلة الرئيسية المتوفرة الدالّة get_type() لكل كلمة في ملف. يجب أن تُرجع الدالّة get_type() إما "int"، أو "float"، أو "str"، بناءً على الكلمة. الإخراج لملف data.txt المتوفر هو:

    str: Hello
    int: 100
    str: times!
    float: 3.14159
    str: is
    str: pi.

جرّب بنفسك

الدول التي تحتوي على كلمة United

اكتب برنامجًا يطلب من المستخدم إدخال كلمة واسم ملف. يجب أن يطبع البرنامج كل سطر من الملف يحتوي على الكلمة. إليك مثال لتشغيل البرنامج (إدخال المستخدم بالخط العريض):

    Enter a word: United
    Enter a filename: countries.csv
    United Arab Emirates,9890402,83600,118
    United Kingdom,67886011,241930,281
    United States of America,331002651,9147420,36

يستخدم هذا المثال ملفًا باسم countries.csv بناءً على القائمة الأبجدية للدول من Worldometer. يتضمن كل سطر في الملف اسم الدولة، وعدد السكان، والمساحة البرية، والكثافة السكانية، مفصولة بفواصل.

قد يكتب المستخدم اسم الملف بشكل غير صحيح (مثال: countries.txt بدلاً من countries.csv). يجب أن يعرض برنامجك رسالة خطأ إذا لم يتم العثور على الملف، ويستمر في مطالبة المستخدم بإدخال اسم ملف حتى يتم العثور عليه:

    ...
    Enter a filename: countries
    File not found: countries
    Enter a filename: countries.txt
    File not found: countries.txt
    Enter a filename: countries.csv
    ...

تلميح: حاول فتح الملف المحدد من قبل المستخدم. يُطلَق FileNotFoundError إذا كان اسم الملف غير صالح.