Výpisy chyb
Na začátku našeho povídání o chybách si ukážeme,
jak se vypisuje chyba, která nastane v zanořené
funkci:
def vnejsi_funkce():
return vnitrni_funkce(0)
def vnitrni_funkce(delitel):
return 1 / delitel
print(vnejsi_funkce())
Traceback (most recent call last):
File "/tmp/ukazka.py", line 7, in
print(vnejsi_funkce())
File "/tmp/ukazka.py", line 2, in vnejsi_funkce
return vnitrni_funkce(0)
File "/tmp/ukazka.py", line 5, in vnitrni_funkce
return 1 / delitel
ZeroDivisionError: division by zero
Všimni si, že každá funkce, jejíš volání vedlo
k chybě, je uvedena ve výpisu.
Skutečná chyba (tedy místo, které musíme opravit)
je pravděpodobně poblíž některého z těchto volání.
V našem případě bychom asi neměly volat
vnitrni_funkce
s argumentem
0
– a nebo by
vnitrni_funkce
měla být na nulu
připravená a dělat v tomto případě něco jiného.
Vyvolání chyby
VELIKOST_POLE = 20
def over_cislo(cislo):
if 0 < cislo <= VELIKOST_POLE:
raise ValueError('Čislo {n} není v poli!'.format(n=cislo))
Všechny typy výjimek, které jsou zabudované
v Pythonu, jsou popsané
v dokumentaci Pythonu
.
Pro nás jsou důležité tyto:
BaseException
├── SystemExit vyvolá funkce exit()
├── KeyboardInterrupt vyvolána po stisknutí Ctrl+C
╰── Exception
├── ArithmeticError
│ ╰── ZeroDivisionError dělení nulou
├── AssertionError nepovedený příkaz `assert`
├── AttributeError neexistující atribut, např. 'abc'.len
├── ImportError nepovedený import
├── LookupError
│ ╰── IndexError neexistující index, např. 'abc'[999]
├── NameError použití neexistujícího jména proměnné
│ ╰── UnboundLocalError použití proměnné, která ještě nebyla nastavená
├── SyntaxError špatná syntaxe – program je nečitelný/nepoužitelný
│ ╰── IndentationError špatné odsazení
│ ╰── TabError kombinování mezer a tabulátorů
├── TypeError špatný typ, např. len(9)
╰── ValueError špatná hodnota, např. int('xyz')
Ošetření chyby
def nacti_cislo():
odpoved = input('Zadej číslo: ')
try:
cislo = int(odpoved)
except ValueError:
print('To nebylo číslo!')
Pokud odchytáváme obecnou výjimku,
chytnou se i všechny podřízené typy výjimek
– například except ArithmeticError:
zachytí i ZeroDivisionError
.
A except Exception:
zachytí všechny
výjimky, které běžně chceme zachytit.
Všechny příkazy
try:
neco_udelej()
except ValueError:
print('Tohle se provede, pokud nastane ValueError')
except NameError:
print('Tohle se provede, pokud nastane NameError')
except Exception:
print('Tohle se provede, pokud nastane jiná chyba')
# (kromě SystemExit a KeyboardInterrupt, ty chytat nechceme)
else:
print('Tohle se provede, pokud chyba nenastane')
finally:
print('Tohle se provede vždycky')
Úkol
Doplň do 1-D piškvorek ošetření chyby, která
nastane když uživatel nezadal číslo.
def tah_hrace(pole):
while True:
try:
pozice = int(input('Kam chceš hrát? '))
except ValueError:
print('To není číslo!')
else:
if pozice < 0 or pozice >= len(pole):
print('Nemůžeš hrát venku z pole!')
elif pole[pozice] != '-':
print('Tam není volno!')
else:
break
pole = pole[:pozice] + 'o' + pole[pozice + 1:]
return pole
print(tah_hrace('-x----'))