Chyby, výjimky, errory. Chyby jsou většinou nemilé, ohlašují nějakou špatnou zprávu. Jde ale o to, jestli nám chybové hlášky sdělují něco více než jen ERROR!. Nás určitě zajímá, kde a proč se tak chyba stala. Dokáže Python pomoci?
Chyby
Nikdo není neomylný, takže každý se dříve či později ve svém programu potká s nějakou chybou. Chyby mohou být obecně dvojí: logické a gramatické. Gramatické chyby nastávají, zjednodušeně řečeno, když napíšete něco špatně (překlep, apod.) a Python vám ohlásí, že se mu to nelíbí. Logické chyby nastávají, když si špatně uvědomíte problém, nesprávně naprogramujete, program sice funguje, ale dává špatné výsledky. Budeme se zabývat samozřejmě těmi gramatickými.
Chyby jsou vaši přátelé
Neměli byste chápat výpisy chyb jako zlo, jako něco špatného. Samozřejmě, je to nepříjemné, že tam máte chyby, ale Python vám chybu pomáhá velmi dobře vyhledat a určit. Nemůže ji za vás opravit, jen napovědět.
Představte si, že napíšete script a Python vám vyhodí tuto hlášku:
ERROR!!!!!
Tak takhle napsaná chyba by byla skutečně nepřítelem, protože vůbec nic neříká o tom kde, kdo a proč asi. Naštěstí je Python přívětivý a chybu nám přesně popíše:
Traceback (most recent call last):
File "C:\Dokumenty\highlow.py", line 8, in ?
if volba==cisl:
NameError: name 'cisl' is not defined
Rozbor chyby
Jednoduchý příklad
Zkusíme si tedy následující výpis chyby rozebrat řádku po řádce:
Traceback (most recent call last):
File "C:\Dokumenty\highlow.py", line 8, in ?
if volba==cisl:
NameError: name 'cisl' is not defined
Řádka Traceback… je startovací řádkou do výpisu chyby. Na druhém řádku je přesný název i umístnění souboru, kde chyba vznikla. A nejen to. Hlavně je tam číslo řádky, kde se chyba stala (line 8). Ve 3. řádce je tato řádka dokonce pro naše pohodlí vypsána :-). No a na posledním řádku je její slovní popis. V překladu snad takto: Chyba ve jménu: jméno 'cisl' není definováno.
Složitější příklad
1. Traceback (most recent call last):
2. File "i:\Python\edu\livewires\B1110955.py", line 149, in ?
3. vyrobRoboty()
4. File "i:\Python\edu\livewires\B1110955.py", line 28, in vyrobRoboty
5. robot.x, robot.y, robot.srot=narozeni()
6. File "i:\Python\edu\livewires\B1110955.py", line 44, in narozeni
7. return randint(0,63), randit(0,47),0
8. NameError: global name 'randit' is not defined
>>>
První řádek nic, ale hned ve druhém řádku je nějaké divné jméno souboru: B1110955.py. Kde se tam vzalo? To nic, to jen můj editor, PSPad, má takovou vlastnost, že když udělám v programu nějaké změny a neuložím je a chci program spustit přes F9, tak si nejdříve program uloží pod náhodným jménem (tentokrát to bylo B1110955.py) a teprve pak pustí. A chyba se stala na řádku 149. Na řádku 149 je ovšem jen volání funkce vyrobRoboty().
Výpis chyb tedy pokračuje dále, na řádce 4 jsme pořád ve stejném souboru, ale již jsme uvnitř funkce vyrobRoboty, a to na řádce 28. Tam je opět volání jiné funkce, tentokrát narozeni(). Asi bude chyba v této funkci, protože výpis pokračuje dále.
Na řádce 6 jsme se dostali do funkce narozeni(), kde hned pod tím vidíme:
return randint(0,63), randit(0,47),0
V této řádce je někde chyba. Když se budeme pozorně dívat, tak ji hned objevíme (pokud tedy známe dobře funkci na náhodnou volbu čísel randint). Nicméně, Python nám ještě napovídá hned pod tím:
Chyba jména: globální jméno 'randit' není definováno.
Další práce je již na nás. Prostě si musíme uvědomit, že jsme udělali překlep a že nám chybí ve slově randit 'n'. Správně tedy 'randint' ;-).
Typy chyb
NameError
Chyba jména nastane většinou, když uděláte překlep v názvu proměnné. Když Python prostě o proměnné, kterou chcete, nikdy předtím neslyšel, nezná ji. Nebo když napíšete místo print primt ;-), což je ale vlstně to samé, protože v tomto případě Python hledá proměnnou 'primt' a nenalézá.
IndexError
Chyba indexu nastává, když se ze seznamu pokoušíte vydolovat prvek, který tam není. Příklad:
>>> jmena=["Curo","Frosty"]
>>> print jmena[10]
Traceback (most recent call last):
File "", line 1, in ?
IndexError: list index out of range
SyntaxError
Python vyvolá tuto chybu, když mu prostě řádek absolutně nedává smysl, když tam něco má být, ale není. Příklad:
if a=b: # má tam být a==b, chybí zde jedno =
if a==b # chybí :
+ # co se má sečíst?
while for: # for není něco, co by mohlo být Pravda nebo Nepravda
Ošetření chyb
Python nejen že dokáže pěkně vypsat, kde chyba je, ale dokáže tu chybu i v programu zachytit a zpracovat, takže ji můžeme využít v náš prospěch. Prostě něco, co zamezí výpisu chyby a tím i skončení programu. Jedná se o příkaz try: … except: ….
Jednoduchá ukázka na dělení nulou:
>>> 5/0
Traceback (most recent call last):
File "", line 1, in ?
ZeroDivisionError: integer division or modulo by zero
Zachycení a ošetření chyby by mohlo vypadat takto:
try: # zkus
print 5/0 # 5/0
except: # pokud se to nepovede
print "Delit nulou nelze." # dej o tom vědět
Úkol
V následujícím příkladu je spousta chyb. Opravte je. Většina je gramatických, ale mohou tam být i logické. Program musí prostě fungovat správně.
import random
cislo=random.randint(1,100)
pritn 'Myslím si cislo, uhodni jake
while x:
volba=imput('Jake cislo si myslim? ')
if volba=cisl:
print "Uhodl jsi"
break
if Volba>cislo:
print "Je to malo"
elif Volba>cislo:
print "Je to moc"