קורס Python שיעור טיפול בחריגים (Exceptions)


זה נושא דיון מלווה לערך המקורי ב- https://www.tocode.co.il/bundles/python/lessons/exceptions

הי,
לא כ"כ הבנתי מתי אני משתמש ב try ומתי ב raise

הי,

הפקודות try ו raise משלימות אחת את השניה: ב raise נשתמש כדי לסמן שמשהו התרחש לא לפי התוכנית וב try נשתמש כדי לזהות קריאה ל raise.

במילים אחרות raise תופיע בתוך פונקציה שרוצה לסמן לקוד שקורא לה שמשהו מוזר קרה, ו try יופיע בקוד שמפעיל פונקציה כדי לטפל במקרים שמשהו מוזר קרה.

אנסה דוגמא נוספת-
ניקח תוכנית שמגדירה מחלקה עבור מכונית ומחלקה זו יודעת להגיד מה המחיר של מכונית לפי הצבע שלה (כי ידוע שמכוניות צהובות עולות יותר). הקוד יוכל להיראות כך:

class CarShop:
    def get_price_by_color(self, color):
        if color == 'red':
            return 8
        elif color == 'blue':
            return 15
        elif color == 'yellow':
            return 91
        elif color == 'black':
            return 50

shop = CarShop()
print shop.get_price_by_color('yellow')

עכשיו נשאל - מה קורה אם מישהו מעביר ערך שהוא לא צבע או שאנחנו לא יודעים לייצר מכונית בצבע הזה? ולזה יש בפייתון שני היבטים.

ההיבט הראשון הוא מתוך גוף הפונקציה שצריכה להודיע למי שקרא לה שאין לה מושג כמה עולה מכונית בצבע הזה כי היא לא מכירה את הצבע. אי אפשר להשתמש כאן ב return כי כל הרצף של התוכנית ייפגע כי return אמור להחזיר מספר. לכן היא מסמנת באמצעות raise שמשהו מוזר קרה:

class CarShop:
    def get_price_by_color(self, color):
        if color == 'red':
            return 8
        elif color == 'blue':
            return 15
        elif color == 'yellow':
            return 91
        elif color == 'black':
            return 50
        else:
            raise Exception("Unknown color {}".format(color))

מצד שני הקוד הראשי יכול להחליט שהוא רוצה להוסיף איזה טיפול מיוחד בהודעת השגיאה ולמשל להגיד למשתמש שינסה לבחור צבע אחר. הנה לולאה שעושה בדיוק את זה:

shop = CarShop()
while True:
    try:
        color = raw_input('please select a color for your car: ')
        print('it costs ${}'.format(shop.get_price_by_color(color)))
        break
    except Exception:
        print("Sorry we don't have that color. Care to try another one?")

הי,
נסיתי את התוכנית הזאת אצלי והגעתי למסקנות הבאות:
כאשר יש טעות מובנית בפייתון (למשל ValueError) אז ניתן לתפוס אותה ע"י

except ValueError

אך כאשר זה לא משהו מובנה, אין מונח ספציפי שאפשר לרשום אותו ב except
ולכן צריכים להשתמש ב raise Exception כדי להודיע לפייתון שיש חריג חדש שאנחנו המצאנו ויש להתחשב בו ואת זה עושים ע"י except Exception בהמשך התוכנית. האם הבנתי נכון?

מה שלא הבנתי הוא למה צריך לרשום את הפורמט הבא אם הוא לא מודפס בשום מקום…

("Unknown color {}".format(color))

כמעט נכון,
אפשר גם ליצור Exception Classes משלנו (כפי שמוסבר בשיעור) במקום להשתמש ב Exception הכללי של פייתון.

לגבי ההודעה הטקסט נשמר בשדה message של אותו Exception Object. למשל הקטע הבא מתוך תוכנית הדוגמא שהוצגה בשיעור מדפיס גם את ההודעה:

import math
def sqrt(n):
    return math.sqrt(n)

try:
    print sqrt(-1)
except ValueError as e:
    print "Failed to calculate sqrt of -1. Error was: %s" % e.message