2.25. Rukovanje pogreškama

Većina problema tijekom izvođenja u Pythonu pojavljuje se kao iznimke – imenovan, strukturiran način prijavljivanja da je nešto pošlo po zlu. ValueError, TypeError, KeyError, OSError, MemoryError svi su primjeri; svaki je klasa, a podizanje jedne zaustavlja trenutni poziv i traži rukovatelja u okolnom kodu.

2.25.1. try / except

Omotajte blok koda u try da biste uhvatili svaku iznimku koju podigne:

try:
    n = int(input_text)
except ValueError:
    n = 0

Ako pretvorba int(...) ne uspije, upravljanje skače na except blok umjesto daljnjeg širenja pogreške. Ako je input_text bio valjani niz cijelog broja, except blok se preskače.

Jedan try može imati nekoliko except blokova, od kojih svaki hvata drugačiju vrstu pogreške:

try:
    value = data[key]
except KeyError:
    value = None
except TypeError:
    value = -1

Python uspoređuje redom; prvi čija klasa iznimke odgovara rješava problem. Hvatanje Exception (osnovne klase za gotovo sve) rješava bilo koju pogrešku; to rezervirajte za najvanjskiji sloj programa gdje je alternativa rušenje.

Upozorenje

Goli except: (bez klase nakon ključne riječi) također hvata KeyboardInterrupt – iznimku koju IDE šalje kada pritisnete njegovu tipku stop za prekid skripte koja se izvodi. Petlja omotana u goli except: pass progutat će prekid i nastaviti se izvoditi, ne ostavljajući nikakav način za zaustavljanje skripte osim ponovnog pokretanja napajanja.

Preferirajte except Exception: umjesto golog except: kada zaista trebate hvatati široko. KeyboardInterrupt nasljeđuje od BaseException, a ne od Exception, pa except Exception: ostavlja tipku za zaustavljanje funkcionalnom.

2.25.1.1. Pregledavanje iznimke

Da biste pročitali poruku priloženu uz iznimku, imenujte je pomoću as:

try:
    f = open("data.txt")
except OSError as e:
    print("could not open file:", e)

Varijabla vezana pomoću as valjana je samo unutar except bloka.

2.25.2. else i finally

try blok ima dva neobavezna dodatka.

else se izvršava samo kada try završi bez podizanja iznimke:

try:
    value = compute()
except ValueError:
    print("bad input")
else:
    print("got", value)

Stavljanje „što učiniti kada je uspjelo” u else zadržava try blok uskim – samo redak koji bi mogao podbaciti pripada u try.

finally se izvršava na kraju bez obzira na sve – bilo da je try uspio, podigao iznimku koja je obrađena, ili podigao iznimku koja se sprema širiti:

try:
    do_work()
finally:
    cleanup()
Dijagram toka koji prikazuje četiri moguća puta kroz try / except / else / finally: uspjeh ide u else pa finally; uhvaćena iznimka ide u except pa finally; neuhvaćena iznimka ide u finally pa se širi dalje.

finally se uvijek izvršava. else se izvršava samo na putu bez iznimke.

Za većinu obrazaca dohvati/oslobodi, preferirajte upravitelj konteksta umjesto para try / finally – sam resurs upravlja vlastitim čišćenjem.

2.25.3. Uobičajene ugrađene iznimke

Kratak popis iznimki na koje ćete često nailaziti:

  • ValueError – pravi tip, pogrešna vrijednost (bytes([300]) – 300 je pravi tip, ali je izvan valjanog raspona bajta 0..255).

  • TypeError – potpuno pogrešan tip (len(42)).

  • KeyError – nedostajući ključ u dict.

  • IndexError – indeks iza kraja niza.

  • AttributeError – pristup atributu koji ne postoji ("abc".foo).

  • OSError – neuspjeh datotečnog sustava ili U/I.

  • MemoryError – nestalo je memorije na hrpi (heap). Na izvođačkom okruženju s ograničenom memorijom ovo se može dogoditi tijekom normalnog rada – ne samo u patološkim slučajevima.