Co je to Python Try Except a proč je důležité?
Konstrukce try-except
v jazyce Python je klíčová pro robustní a bezproblémové zpracování chyb, nazývaných výjimky. Bez správného ošetření výjimek by programy často selhávaly a padaly. Tento článek vám ukáže, jak se s výjimkami vypořádat, v jakých situacích je to nejvhodnější a jak je sami vyvolávat.
Výjimky: Nečekané problémy při běhu
Výjimky jsou signály, že se během chodu programu objevila nějaká anomálie nebo chyba. Pokud nejsou ošetřeny, vedou k ukončení programu. Zpracování výjimek umožňuje programátorovi na tyto situace reagovat a zajistit tak plynulý chod programu.
Podívejme se na příklad:
user_input = input("Zadejte číslo: ") num = int(user_input) print("Vaše číslo zdvojnásobené je:", num * 2)
Na první pohled vypadá kód bezchybně. Získá od uživatele vstup, převede ho na celé číslo a následně ho zdvojnásobí. Pokud uživatel zadá například číslo 5, program funguje správně.
Ovšem, pokud uživatel zadá například „ahoj“, program selže. Řetězec „ahoj“ totiž nelze převést na celé číslo, což vede k vyvolání výjimky a ukončení programu.
Proč vznikají výjimky a proč je ošetřovat?
Programy se často skládají z menších funkcí, které provádějí specifické úlohy. Tyto funkce mohou během svého běhu narazit na problémy, se kterými si samy neumí poradit. Namísto toho, aby program bez vysvětlení selhal, vyvolají výjimku, aby informovaly o problému. Funkce, která volá funkci, je zodpovědná za to, že bude naslouchat těmto výjimkám a reagovat na ně. Když se s nimi nezachází, program padne.
Výjimky jsou tedy jakýmsi nouzovým signálem, který funkce posílá kódu, který ji volal. Správné zpracování výjimek je podstatou robustního programování.
Různé druhy výjimek
Je důležité si uvědomit, že existují různé druhy výjimek, které signalizují různé typy chyb. Například, pokud se pokusíte dělit nulou, dojde k výjimce ZeroDivisionError
. Pokud se pokusíte provést operaci s nesprávným datovým typem, vyvolá se výjimka TypeError
. Úplný seznam typů výjimek naleznete zde.
Jak zacházet s výjimkami
Jak už víme, výjimky jsou nouzové signály od funkcí. Náš kód by měl na tyto signály reagovat. Používáme k tomu konstrukci try-except
. Základní struktura je následující:
try: # Kód, který se má zkusit spustit except: # Kód, který se spustí v případě výjimky finally: # Kód, který se spustí nakonec, ať už výjimka nastala, nebo ne
Tato konstrukce obsahuje tři klíčová slova:
try
Klíčové slovo try
ohraničuje blok kódu, u kterého očekáváme, že může vyvolat výjimku. Program se pokusí spustit tento kód. Pokud v bloku try
dojde k výjimce, program okamžitě přeskočí na blok except
.
except
Klíčové slovo except
označuje blok kódu, který se spustí, pokud během provádění bloku try
dojde k výjimce. Je možné mít i více bloků except
pro různé typy výjimek.
finally
Klíčové slovo finally
označuje blok kódu, který se spustí vždy, a to bez ohledu na to, zda výjimka nastala, nebo ne. Používá se například k uvolnění prostředků.
Příklad
Zde je upravený příklad z úvodu, který nyní ošetřuje potenciální výjimku:
try: user_input = input("Zadejte číslo: ") num = int(user_input) print("Vaše číslo zdvojnásobené je:", num * 2) except: print("Něco se pokazilo") finally: print("Tento kód se provede vždy")
Pokud program spustíte se vstupem 5, získáte výstup, který ukazuje, že kód byl úspěšný, a provede se blok finally
.
Pokud ovšem zadáte „ahoj“, program už nespadne, ale vypíše chybové hlášení a provede se blok finally
.
Můžeme také ošetřit specifické výjimky. Pokud chceme specificky ošetřit ValueError
a KeyboardInterrupt
, můžeme kód upravit takto:
try: user_input = input("Zadejte číslo: ") num = int(user_input) print("Vaše číslo zdvojnásobené je:", num * 2) except ValueError: print("Hodnotu nelze převést na celé číslo") except KeyboardInterrupt: print("Přerušení z klávesnice") except: print("Blok pro všechny ostatní výjimky") finally: print("Tento kód se provede vždy")
V tomto případě máme tři bloky except
. První zachytí pouze ValueError
, druhý KeyboardInterrupt
a poslední zachytí všechny ostatní výjimky. Pokud zadáme například text „abc“, zachytí to první blok.
Výstup je následující:
Můžeme také získat přístup k samotné výjimce pomocí klíčového slova as
:
try: user_input = input("Zadejte číslo: ") num = int(user_input) print("Vaše číslo zdvojnásobené je:", num * 2) except ValueError as e: print("Chyba hodnoty:", e) except KeyboardInterrupt as e: print("Přerušení klávesnice:", e) except Exception as e: print("Jiná výjimka:", e)
Jak vyvolávat výjimky
Doposud jsme se zabývali výjimkami, které vyvolávají jiné funkce. Ale i vy můžete ve svém kódu výjimky vyvolávat. Používá se k tomu klíčové slovo raise
. Spolu s raise
určíme třídu výjimky a zprávu, která s výjimkou souvisí.
Například, pokud chceme vyvolat obecnou výjimku, použijeme třídu Exception
a předáme zprávu:
raise Exception('Něco se pokazilo')
Pokud tento kód spustíte, získáte následující výstup:
Můžeme samozřejmě vyvolávat i jiné typy výjimek. Například, pokud má hodnota nesprávný datový typ, můžeme vyvolat TypeError
:
def double(x): if isinstance(x, int): return x * 2 else: raise TypeError('x musí být celé číslo')
Nebo pokud je zadaná hodnota mimo přijatelný rozsah, vyvoláme ValueError
:
def say_hello(name): if name == '': raise ValueError('Hodnota je mimo povolený rozsah') else: print('Ahoj', name)
Můžete také vytvářet své vlastní typy výjimek tím, že je podědíte od třídy Exception
. Například:
class InvalidHTTPMethod(Exception): pass
Vytvořili jsme třídu InvalidHTTPMethod
, kterou můžeme používat k vyvolávání výjimek:
raise InvalidHTTPMethod('Musí to být GET nebo POST')
Běžné případy použití zpracování výjimek
Zpracování výjimek je užitečné v mnoha situacích. Viděli jsme, jak se dá použít k ošetření výjimek při zadávání vstupu od uživatele. Nyní si ukážeme, jak se dá použít při odesílání síťových požadavků a při čtení souborů.
Odesílání síťových požadavků
Následující příklad ukazuje, jak odeslat požadavek na server Google a ošetřit potenciální výjimky:
import requests try: response = requests.get("https://google.com") # Kontrola, zda je stavový kód v rozmezí 200-299 (úspěšný požadavek) if 200 <= response.status_code < 300: print("Požadavek byl úspěšný!") else: print(f"Požadavek selhal se stavovým kódem: {response.status_code}") except requests.exceptions.RequestException as e: print(f"Došlo k chybě RequestException: {e}") except requests.exceptions.ConnectionError as e: print(f"Došlo k chybě ConnectionError: {e}") except requests.exceptions.Timeout as e: print(f"Došlo k chybě Timeout: {e}") except requests.exceptions.TooManyRedirects as e: print(f"Došlo k chybě TooManyRedirects: {e}") except requests.exceptions.HTTPError as e: print(f"Došlo k chybě HTTPError: {e}") except Exception as e: print(f"Došlo k neočekávané chybě: {e}")
Čtení dat ze souboru
V tomto příkladě se pokusíme přečíst data ze souboru hello.txt
a zároveň ošetřit možné výjimky:
try: with open(file_path, 'r') as file: data = file.read() print("Obsah souboru:") print(data) except FileNotFoundError as e: print(f"Došlo k chybě FileNotFound: {e}") except IOError as e: print(f"Došlo k chybě IOError: {e}") except Exception as e: print(f"Došlo k neočekávané chybě: {e}")
Závěr
Tento článek se věnoval tomu, jak výjimky fungují a proč je důležité je ošetřovat. Naučili jsme se, jak s nimi zacházet pomocí konstrukce try-except
a také, jak výjimky sami vyvolávat. Doufáme, že vám tento průvodce pomůže psát robustnější a spolehlivější kód.
Nezapomeňte se podívat i na další běžné typy chyb v jazyce Python a na to, jak je řešit.