Sobes.tech
Middle

Πώς λειτουργούν οι εμφωλευμένες εξαιρέσεις στην Python;

sobes.tech AI

Απάντηση από AI

Οι εμφωλευμένες εξαιρέσεις, γνωστές και ως αλυσίδα εξαιρέσεων, επιτρέπουν την αποθήκευση πληροφοριών σχετικά με την προηγούμενη εξαίρεση κατά την εμφάνιση μιας νέας. Αυτό είναι χρήσιμο για αποσφαλμάτωση και κατανόηση των αιτίων του σφάλματος.

Στην Python 3, κατά κανόνα, όταν προκύψει μια νέα εξαίρεση μέσα σε μπλοκ except ή finally, η αρχική εξαίρεση συνδέεται αυτόματα με τη νέα.

Αυτή η σύνδεση αποθηκεύεται στο χαρακτηριστικό __cause__ της νέας εξαίρεσης.

Η ρητή σύνδεση μπορεί να πραγματοποιηθεί με τη χρήση της λέξης-κλειδιού raise from.

# Παράδειγμα αυτόματης σύνδεσης
def divide(a, b):
    try:
        return a / b
    except TypeError:
        # Κατά την επεξεργασία του TypeError μπορεί να προκύψει άλλη εξαίρεση
        # Η αρχική εξαίρεση (TypeError) θα συνδεθεί με τη νέα
        raise ValueError("Λάθος τύπος τελεστών")

try:
    divide("a", 0)
except ValueError as e:
    # e.__cause__ θα περιέχει το TypeError
    print(f"Παρουσιάστηκε σφάλμα: {e}")
    if e.__cause__:
        print(f"Κλήθηκε από: {e.__cause__}")

print("-" * 20)

# Παράδειγμα ρητής σύνδεσης με raise from
class CustomError(Exception):
    pass

def tricky_function():
    try:
        # Απόπειρα διαίρεσης με το μηδέν, προκαλεί ZeroDivisionError
        result = 1 / 0
    except ZeroDivisionError as original_exc:
        # Δημιουργούμε μια νέα εξαίρεση και τη συνδέουμε με την αρχική
        raise CustomError("Σφάλμα κατά τον υπολογισμό") from original_exc

try:
    tricky_function()
except CustomError as e:
    # e.__cause__ θα περιέχει ZeroDivisionError
    print(f"Παρουσιάστηκε σφάλμα: {e}")
    if e.__cause__:
        print(f"Κλήθηκε από: {e.__cause__}")

print("-" * 20)

# Απόκρυψη σύνδεσης με raise ... from None
try:
    try:
        # Αρχικό σφάλμα
        raise ValueError("Αρχικό σφάλμα")
    except ValueError:
        # Κατά την επεξεργασία του ValueError προκύπτει άλλο σφάλμα,
        # αλλά η σύνδεση αποκρύπτεται
        raise TypeError("Νέο σφάλμα") from None
except TypeError as e:
    # e.__cause__ εδώ θα είναι None
    print(f"Παρουσιάστηκε σφάλμα: {e}")
    if e.__cause__ is None:
        print("Ο λόγος δεν δηλώθηκε.")

Η λέξη-κλειδί raise χωρίς ορίσματα επανεκκινεί την τελευταία εξαίρεση.

# Παράδειγμα επανεκκίνησης εξαίρεσης
def process_data(data):
    try:
        # Υποθέτουμε ότι εδώ μπορεί να πάει κάτι στραβά
        if not data:
            raise ValueError("Απουσία δεδομένων")
        print("Τα δεδομένα επεξεργάστηκαν")
    except ValueError:
        print("Πιάσαμε το ValueError")
        # Επανεκκινούμε την ίδια εξαίρεση
        raise

try:
    process_data("")
except ValueError as e:
    print(f"Πιάσαμε την επανεκκινημένη εξαίρεση: {e}")

Οι εμφωλευμένες εξαιρέσεις βελτιώνουν την αναγνωσιμότητα των διαδρομών σφαλμάτων και βοηθούν στην ταχύτερη εντοπισμό της αρχικής αιτίας του προβλήματος.