U Pajtonu, konstrukcija try-except
omogućava elegantno upravljanje izuzecima, čime se izbegava prekid rada programa.
Ovakav pristup čini kod pouzdanijim i smanjuje verovatnoću njegovog pada. Ovaj tekst objašnjava kako se rukuje izuzecima i navodi uobičajene situacije u kojima je obrada izuzetaka od ključne važnosti. Pored toga, objasnićemo i kako da sami izazovete izuzetke.
Šta je rukovanje izuzecima?
Izuzeci predstavljaju kritične anomalije i greške koje se javljaju tokom izvršavanja programa. Ako se ne obrade, izuzeci mogu dovesti do pada programa. Zato je rukovanje izuzecima način da se spreči takav ishod.
Evo primera koji ilustruje šta je zapravo izuzetak:
user_input = input("Unesite broj: ") num = int(user_input) print("Duplo od unetog broja je:", num * 2)
Na prvi pogled, ne čini se da u gornjem kodu ima bilo kakvih problema. Program preuzima unos od korisnika, konvertuje ga u ceo broj i prikazuje dvostruku vrednost.
Program funkcioniše bez problema ako se pokrene sa unosom kao što je broj 5. Pogledajte rezultat:
Međutim, ako isti program pokrenemo sa unosom „zdravo“, program će se srušiti. String „zdravo“ ne može se konvertovati u ceo broj, što dovodi do izuzetka i prekida rada programa.
Zašto dolazi do izuzetaka i zašto ih treba obraditi?
Do izuzetaka dolazi jer se često programi dele na funkcije. Ove funkcije se zatim pozivaju da izvrše različite zadatke.
U prethodnom primeru, prvo pozivamo funkciju input
da preuzme korisnički unos, zatim funkciju int
da konvertuje unos u ceo broj, i na kraju, funkciju print
da prikaže rezultat.
Međutim, tokom izvršavanja svojih zadataka, funkcije mogu naići na greške sa kojima ne znaju kako da se nose. U takvim slučajevima, funkcije moraju da prekinu rad i prijave grešku. Da bi to učinile, one „podignu“ izuzetke.
Kod koji je pozvao funkciju odgovoran je za „osluškivanje“ ovih izuzetaka i njihovo adekvatno rešavanje. Ako to ne uradi, program će se srušiti čim naiđe na grešku, kao što smo videli u prethodnom primeru.
Stoga, izuzeci su u osnovi komunikacioni mehanizam koji omogućava da pozvana funkcija pošalje signal „opasnosti“ kodu koji ju je pozvao. Adekvatan odgovor na taj signal predstavlja suštinu rukovanja izuzecima.
Različite vrste izuzetaka
Važno je znati da nisu svi izuzeci isti. Postoje različite vrste izuzetaka za različite vrste grešaka. Na primer, ako pokušate da podelite broj sa nulom, pojaviće se greška ZeroDivisionError
. TypeError
se javlja kada pokušate da izvršite operaciju sa neodgovarajućim tipom podataka. Kompletan spisak vrsta izuzetaka možete naći ovde.
Kako rukovati izuzecima
Kao što je već objašnjeno, izuzeci su signali upozorenja koje generišu pozvane funkcije. Naš kod treba da osluškuje ove signale i da reaguje na odgovarajući način. Da bismo pravilno rukovali izuzecima, koristimo try-except
konstrukciju u Pajtonu. Osnovna struktura ove konstrukcije izgleda ovako:
try: # Kod koji se potencijalno može izvršiti except: # Kod koji se izvršava ako dođe do izuzetka finally: # Kod koji se izvršava na kraju, bez obzira da li je došlo do izuzetka
Kao što vidite, ova konstrukcija se sastoji od tri ključne reči, objašnjene u nastavku:
try
Ključna reč try
označava početak try-except
konstrukcije i označava blok koda koji bi potencijalno mogao da izazove izuzetak. Ovo je instrukcija Pajton interpretatoru da pokuša da izvrši kod u tom bloku. Ako dođe do izuzetka, program se odmah zaustavlja i prelazi na izvršavanje koda u except
bloku.
except
Ključna reč except
označava blok koda koji se izvršava ako dođe do izuzetka tokom izvršavanja koda u try
bloku. Možete definisati više except
blokova za različite tipove izuzetaka. Ovo će biti ilustrovano kasnije.
finally
Ključna reč finally
je treća i poslednja ključna reč koja se koristi u try-except
konstrukciji. Ona označava blok koda koji se izvršava bez obzira da li je došlo do izuzetka ili ne.
Primer
Evo primera kako se navedene ključne reči mogu koristiti za obradu izuzetka. Modifikovaćemo prethodni primer:
try: user_input = input("Unesite broj: ") num = int(user_input) print("Duplo od unetog broja je:", num * 2) except: print("Došlo je do greške") finally: print("Ovaj kod će se uvek izvršiti")
Ako pokrenete gornji kod sa unetim brojem 5, dobićete sledeći izlaz:
A ako pokrenete kod sa unosom „zdravo“, dobićete sledeći izlaz:
Dakle, kada nije došlo do izuzetka tokom izvršavanja koda u try
bloku, program je prešao na finally
blok. Međutim, kada je došlo do izuzetka, program je prešao na except
blok, a zatim na finally
blok.
Takođe možete da obrađujete izuzetke za određene vrste grešaka. Na primer, ako želite da posebno obrađujete ValueError
i KeyboardInterrupt
izuzetke, možete izmeniti gornji kod na sledeći način:
try: user_input = input("Unesite broj: ") num = int(user_input) print("Duplo od unetog broja je:", num * 2) except ValueError: print("Vrednost ne može da se konvertuje u ceo broj") except KeyboardInterrupt: print("Primljen prekid sa tastature") except: print("Opšti blok za obradu izuzetaka") finally: print("Ovaj kod će se uvek izvršiti")
U gornjem kodu, imamo 3 except
bloka. Prvi blok obrađuje samo ValueError
izuzetke, dok drugi obrađuje samo KeyboardInterrupt
izuzetke. Poslednji except
blok nema definisan specifičan tip izuzetka, tako da obrađuje sve ostale izuzetke koji nisu uhvaćeni u prva dva bloka.
Pokretanjem ovog koda, trebalo bi da dobijete izlaz sličan ovom:
Kada se izuzetak podigne, možete dobiti više informacija o njemu kroz objekat izuzetka. Da biste pristupili tom objektu, koristite ključnu reč as
. Ona se koristi na sledeći način:
try: user_input = input("Unesite broj: ") num = int(user_input) print("Duplo od unetog broja je:", num * 2) except ValueError as e: print("Greška u vrednosti:", e) except KeyboardInterrupt as e: print("Prekid sa tastature:", e) except Exception as e: print("Neka druga greška:", e)
Kako izazvati izuzetke
Do sada smo se bavili izuzecima koje su izazvale druge funkcije. Međutim, moguće je i da sami izazovete izuzetke u svom kodu. Da bismo to uradili, koristimo ključnu reč raise
. Takođe navodimo klasu koja predstavlja tip izuzetka koji želimo da izazovemo i poruku koja je razumljiva ljudima, povezanu sa tim izuzetkom.
U sledećem primeru koristimo klasu Exception
da izazovemo generički izuzetak. Zatim prosljeđujemo poruku konstruktoru klase.
raise Exception('Došlo je do greške')
Ako pokrenete gornji isečak kao program, dobićete izlaz sličan ovom:
Takođe, možete navesti različite vrste izuzetaka. Na primer, možete izazvati TypeError
izuzetak kada vrednost ima pogrešan tip podataka:
def double(x): if isinstance(x, int): return x * 2 else: raise TypeError('x mora biti ceo broj')
Ili ako je uneta vrednost izvan prihvatljivih granica, možete izazvati ValueError
:
def say_hello(name): if name == '': raise ValueError('Vrednost van opsega') else: print('Zdravo', name)
Možete takođe da kreirate sopstvene tipove izuzetaka nasledjivanjem Exception
klase. Evo primera:
class InvalidHTTPMethod(Exception): pass
U gornjem primeru, kreirali smo klasu InvalidHTTPMethod
, koja nasleđuje Exception
klasu. Možemo je koristiti na isti način kao i ranije za izazivanje izuzetaka:
raise InvalidHTTPMethod('Mora biti GET ili POST')
Uobičajeni slučajevi upotrebe za obradu izuzetaka
Obrada izuzetaka se koristi u mnogim situacijama. Prethodni primer je pokazao kako se može obraditi izuzetak uzrokovan korisničkim unosom. Ovaj odeljak će pokriti još dve situacije u kojima je obrada izuzetaka korisna: obrada izuzetaka koji nastaju kao rezultat neuspešnih mrežnih zahteva i obrada izuzetaka prilikom čitanja datoteka.
Slanje mrežnih zahteva
U primeru ispod, šaljemo zahtev Google-u. Osluskujemo izuzetke da bismo mogli da ih obradimo. Ovi izuzeci su definisani u modulu requests.exceptions
.
import requests try: response = requests.get("https://google.com") # Provera da li je statusni kod odgovora u opsegu 200-299 (uspešan odgovor) if 200 <= response.status_code < 300: print("Zahtev je bio uspešan!") else: print(f"Zahtev nije uspeo sa statusnim kodom: {response.status_code}") except requests.exceptions.RequestException as e: print(f"Došlo je do RequestException greške: {e}") except requests.exceptions.ConnectionError as e: print(f"Došlo je do ConnectionError greške: {e}") except requests.exceptions.Timeout as e: print(f"Došlo je do Timeout greške: {e}") except requests.exceptions.TooManyRedirects as e: print(f"Došlo je do TooManyRedirects greške: {e}") except requests.exceptions.HTTPError as e: print(f"Došlo je do HTTPError greške: {e}") except Exception as e: print(f"Došlo je do neočekivane greške: {e}")
Čitanje podataka iz datoteke
U ovom poslednjem primeru, čitamo podatke iz datoteke hello.txt
. Takođe obrađujemo uobičajene izuzetke koji se mogu pojaviti, kao što su FileNotFoundError
i IOError
.
try: with open(file_path, 'r') as file: data = file.read() print("Sadržaj datoteke:") print(data) except FileNotFoundError as e: print(f"Došlo je do FileNotFoundError greške: {e}") except IOError as e: print(f"Došlo je do IOError greške: {e}") except Exception as e: print(f"Došlo je do neočekivane greške: {e}")
Zaključak
Ovaj tekst je objasnio šta su izuzeci i zašto se javljaju. Takođe smo videli da je potrebno njima rukovati da bi kod bio pouzdaniji i da bi se izbeglo njegovo rušenje. Na kraju, opisali smo kako se rukuje izuzecima i kako da sami izazovete izuzetke.
Pogledajte takođe uobičajene greške u Pajtonu i kako ih rešiti.