Výjimky

Chyby v Pythonu můžeme rozlišit na syntaktické chyby a chyby za běhu (run-time). Syntaktické chyby jsou způsobeny např. nespárovanými závorkami, špatným odsazením apod. Program se syntaktickými chybami nelze vůbec spustit. Častější jsou run-time chyby, které vznikají nesprávným použitím nějaké funkce, chybějícími daty apod. Jelikož je Python interpretovaný jazyk, většina chyb se ukáže až za běhu, na rozdíl od kompilovaných jazyků, kde se mnoho chyb objeví při kompilaci.

Výjimky

Výjimka (exception) je vyhozena ve chvíli, kdy dojde k chybě. Pokud tuto výjimku nezachytíme (viz dále), běh programu se přeruší. Např. dělení nulou skončí výjimkou ZeroDivisionError:

In [1]:
1/0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Cell In[1], line 1
----> 1 1/0

ZeroDivisionError: division by zero

Chytáme výjimky

Pokud nechceme, aby běh programu skončil ve chvíli výjimky, můžeme použít try - except blok. Ten funguje tak, že rizikovou část kód umístíme do try bloku, do except bloku pak umístíme instrukce pro případ chyby (výjimky).

In [2]:
try:
    1/0
except:
    print("nulou se nedělí!")
nulou se nedělí!

Takto použitý except odchytí všechny výjimky. To není obvykle dobrá praktika, je lepší odchytávat pouze určité výjimky (takové, které očekáváme, že mohou nastat). Pro odchycení dělení nulou by to vypadalo asi takto:

In [3]:
try:
    1/0
# do proměnné e se uloží vyhozená výjimka
except ZeroDivisionError as e:
    print("nulou se nedělí!")
    print(e)
nulou se nedělí!
division by zero

Kompletní try-except blok může ještě obsahovat else a finally bloky, viz dokumentace. finally se hodí zejména pro "úklid", např. zavření souboru apod.

Vyhazujeme výjimky

Výjimku můžeme samozřejmě vyhodit i v našem kódu pomocí klíčového slova raise. Pokud bychom chtěli např. kontrolovat vstup nějaké funkce, uděláme to takto:

In [4]:
def fact(n):
    """Spočítá faktoriál
    """
    from math import factorial
    try:
        # zkusíme převést n na číslo
        n = float(n)
    except ValueError as e:
        raise ValueError("{} není číslo".format(n))
    # je n celé číslo >= 0
    if not n.is_integer() or n < 0:
        raise ValueError("{} není celé číslo >= 0".format(n))
    else:
        n = int(n)
    return factorial(n)
# jednodychý test
n = 4
print('{}! = {}'.format(n, fact(n)))
4! = 24
In [5]:
# teď zkusíme, jestli fungují naše výjimky
for n in (4.0, "0", 3.2, -1):
    try:
        print('{}! = {}'.format(n, fact(n)))
    # Exception odchytí v podstatě jakoukoli výjimku, ostatní výjimky totiž od ní dědí
    except Exception as e:
        print(e)
4.0! = 24
0! = 1
3.2 není celé číslo >= 0
-1.0 není celé číslo >= 0

Traceback

Pomocí modulu traceback si můžeme nechat vypsat podrobnější informace jak k vyjímce došlo:

In [6]:
import traceback, sys

try:
    fact(1.1)
except Exception:
    traceback.print_exc(file=sys.stdout)
Traceback (most recent call last):
  File "/tmp/ipykernel_900090/36834011.py", line 4, in <module>
    fact(1.1)
  File "/tmp/ipykernel_900090/3537662117.py", line 12, in fact
    raise ValueError("{} není celé číslo >= 0".format(n))
ValueError: 1.1 není celé číslo >= 0
In [7]:
try:
    pass
    # raise ValueError("chyba")
except ValueError:
    print("Tato chyba jo ok")

Komentáře

Comments powered by Disqus