Python - Prilagođeni izuzeci


Kreiranje prilagođenih izuzetaka

U Pythonu korisnici mogu definisati prilagođene izuzetke stvaranjem nove klase. Ova klasa izuzetka mora se izvesti, bilo direktno ili indirektno, iz ugrađene klase Exception. Većina ugrađenih izuzetaka je takođe izvedena iz ove klase.

>>> class CustomError(Exception):
...     pass
...

>>> raise CustomError
Traceback (most recent call last):
...
__main__.CustomError

>>> raise CustomError("Dogodila se greška")
Traceback (most recent call last):
...
__main__.CustomError: Dogodila se greška

Ovdje smo stvorili korisnički definisan izuzetak koji se naziva CustomError koji se nasljeđuje iz klase Exception. Ovaj novi izuzetak, kao i ostali izuzeci, može se pokrenuti korištenjem izraza raise s opcionalnom porukom o grešci.

Kada razvijamo veliki program u Pythonu, dobra je praksa smjestiti sve korisnički definisane izuzetke koje naš program pokreće u zasebnu datoteku. Mnogi standardni moduli to rade. Svoje izuzetke definišu odvojeno kao exceptions.py ili error.py (uopšteno, ali ne uvijek).

Korisnički definisana klasa izuzetka može implementovati sve što normalna klasa može učiniti, ali mi ih obično činimo jednostavnim i jezgrovitim. Većina implementacija deklariše prilagođenu osnovnu klasu i izvodi druge klase izuzetka iz ove osnovne klase. Ovaj koncept će vam biti jasniji u sljedećem primjeru.


Primjer: Korisnički definisani izuzetak u Pythonu

U ovom primjeru ilustovaćemo kako se izuzeci koje definišu korisnici mogu koristiti u programu za podizanje (raise) i hvatanje (catch) grešaka. Ovaj program će tražiti od korisnika da unese broj sve dok pravilno ne pogodi pohranjeni broj. Da bi im pomogli da to shvate, pruža se nagovještaj da li je njihova pretpostavka veća ili manja od pohranjenog broja.

# definisanje korisničkih izuzetaka u Python-u
class Error(Exception):
    """Osnovna klasa za ostale izuzetke"""
    pass


class ValueTooSmallError(Error):
    """Dešava se kada je ulazna vrijednost premala"""
    pass


class ValueTooLargeError(Error):
    """Dešava se kada je ulazna vrijednost prevelika"""
    pass


# morate pogoditi ovaj broj
number = 10

# korisnik pogađa broj dok ga ne pogodi
while True:
    try:
        i_num = int(input("Unesite broj: "))
        if i_num < number:
            raise ValueTooSmallError
        elif i_num > number:
            raise ValueTooLargeError
        break
    except ValueTooSmallError:
        print("Ova je vrijednost premala, pokušajte ponovo!")
        print()
    except ValueTooLargeError:
        print("Ova je vrijednost prevelika, pokušajte ponovo!")
        print()

print("Čestitamo! Pogodili ste broj.")

Definisali smo osnovnu klasu koja se zove Error. Druga dva izuzetka (ValueTooSmallError i ValueTooLargeError) koja je zapravo pokrenuo naš program izvedena su iz ove klase. Ovo je standardni način definisanja korisnički definisanih izuzetaka u programiranju u Pythonu, ali niste ograničeni samo na ovaj način.



Prilagođavanje klasa izuzetaka

Ovu klasu možemo dalje prilagoditi tako da prihvata druge argumente prema našim potrebama. Da biste naučili o prilagođavanju klasa Exception, morate imati osnovno znanje o objektno orijentiranom programiranju OOP. Posjetite lekciju Python objektno orijentirano programiranje da biste započeli učenje o objektno orijentiranom programiranju u Pythonu. Pogledajmo jedan primjer:

class SalaryNotInRangeError(Exception):
    """Iznimka se dešava zbog grešaka u ulaznoj plati.

    Atributi:
        salary -- ulazna plata koja je uzrokovala grešku
        message -- objašnjenje greške
    """

    def __init__(self, salary, message="Plata nije u (5000, 15000) rasponu"):
        self.salary = salary
        self.message = message
        super().__init__(self.message)


salary = int(input("Unesite iznos plate: "))
if not 5000 < salary < 15000:
    raise SalaryNotInRangeError(salary)

Ovdje smo nadjačali konstruktor klase Exception da prihvati naše vlastite prilagođene argumente salary i message. Zatim se konstruktor roditeljske klase Exception poziva ručno s argumentom self.message koristeći super().

Prilagođeni atribut self.salary definisan je da se koristi kasnije. Naslijeđena metoda __str__ klase Exception tada se koristi za prikaz odgovarajuće poruke kada se podigne SalaryNotInRangeError. Takođe možemo prilagoditi samu metodu __str__ nadjačavanjem.

class SalaryNotInRangeError(Exception):
    """Iznimka se dešava zbog grešaka u ulaznoj plati.

    Atributi:
        salary -- ulazna plata koja je uzrokovala grešku
        message -- objašnjenje greške
    """

    def __init__(self, salary, message="Plata nije u (5000, 15000) rasponu"):
        self.salary = salary
        self.message = message
        super().__init__(self.message)

    def __str__(self):
        return f'{self.salary} -> {self.message}'


salary = int(input("Unesite iznos plate: "))
if not 5000 < salary < 15000:
    raise SalaryNotInRangeError(salary)

Da biste saznali više o tome kako se možete rukovati s iznimkama u Pythonu, posjetite lekciju Python Exception Handling.