19. diel - Ošetrenie výnimiek v Pythone Nové
V predchádzajúcej lekcii, Dekorátory druhýkrát - Parametrické a triedne dekorátory, sme dokončili tému s dekorátormi.
V tomto Python tutoriáli si ukážeme, ako ošetriť výnimky v programe a
ako reagovať na používateľské či iné chyby. Naše programy doteraz vždy
"spadli" a ďalej už nepokračovali. Takto si používateľ, samozrejme,
nepredstavuje, že budú fungovať
Prezraďme si malé tajomstvo – čím menej skúseného
používateľa budeme pri návrhu programu predpokladať a čím lepšie mu
program prispôsobíme, tým lepšie sa bude program používať, pretože bude
"blbuvzdorný" a jednoduchý!
Ošetrenie chýb
Vo väčšine nami doteraz vytvorených programov sme používateľovi umožnili urobiť chybu pri číselnom vstupe. Ak by teda používateľ zadal namiesto čísla napríklad písmeno, náš program by spadol.
Teraz si teda ukážeme, ako takéto chyby ošetriť. Ošetrenie sa vykonáva
pomocou bloku try–except:
try: # Block of statements that can raise an error except: # Block of statements that runs when an error occurs
Ak je kód, ktorý môže vyvolať chybu, v bloku try, namiesto
pádu programu sa v prípade chyby blok try preruší a program
pokračuje do bloku except.
Príklad
Úplne jednoduché použitie ošetrenia chýb si ukážme na programe, ktorý načíta dve čísla a vydelí prvé druhým:
try: dividend = float(input("Enter the number you want to divide: ")) divisor = float(input("Enter the number you want to divide by: ")) result = dividend / divisor print(f"The division result is: {result}") except: print("An error occurred!")
Ak nezadáme správne prvé číslo a zadáme namiesto neho napríklad text, nezadáme správne druhé číslo alebo budeme deliť nulou, program nespadne, ale vypíše hlášku "An error occurred!" a pobeží ďalej:
Konzolová aplikácia
Enter the number you want to divide: abc
An error occurred!
Druhy chýb
Chyby sa v Pythone (a v objektových jazykoch všeobecne) nazývajú výnimky. Tie základné sú nasledujúce:
SyntaxError– chyba je v zdrojovom kóde,ZeroDivisionError– pokus o delenie nulou,TypeError– nesprávne použitie dátových typov, napríklad sčítanie reťazca a čísla,ValueError– nesprávna hodnota.
Všetky výnimky nájdeme v dokumentácii Pythonu.
V Pythone môžeme zachytiť iba konkrétne chyby a získať aj ich chybovú správu. Potom musíme kód upraviť takto:
except exception_name as error: #The exception text is stored in the error variable.
Bloky else a
finally
Do bloku try–except možno prípadne pridať aj
ďalšie dva bloky:
- Blok
else, ktorý sa hodí pre kód, ktorý má bežať len vtedy, keď všetko vtryprebehne v poriadku. - Blok
finally, ktorý sa potom spustí vždy, či už k chybe došlo, alebo nie. Typicky sa používa na upratovanie – zatvorenie súborov, uvoľnenie zdrojov, odhlásenie atď.
Poďme si to celé zrekapitulovať:
try: # Code that can raise an error except: # Runs when an error occurs else: # Runs only when there was NO exception in try finally: # Always runs.
Pokročilý príklad
Ukážme si príklad, ktorý využije všetky kľúčové slová bloku
try–except a zároveň bude inteligentnejšie
vypisovať, čo sa pokazilo podľa typu zachytenej výnimky:
continue_program = True while continue_program: try: dividend = float(input("Enter the number you want to divide: ")) divisor = float(input("Enter the number you want to divide by: ")) result = dividend / divisor except ZeroDivisionError: print("Division by zero is not possible!") except ValueError: print("An invalid value was entered!") else: print(f"The division result is: {result}") finally: exit_answer = input("Do you want to exit the program? (yes/no): ").lower() if exit_answer == "yes": continue_program = False
Kód si vysvetlíme. V tomto kóde sa program používateľa opýta, ktoré
čísla chce deliť. Ak používateľ skúsi deliť nulou, program chybu
zachytí a vypíše chybovú správu. Rovnako dôjde k zachyteniu chyby v
prípade, že používateľ vloží niečo iné ako číslo. Blok
else sme použili na výpis výsledku delenia v prípade, že
nedôjde k výnimke. Blok finally potom umožňuje používateľovi
opustiť cyklus a ukončiť program.
Kalkulačka
Teraz si ukážeme, ako vytvoriť jednoduchú objektovú aplikáciu so zachytávaním výnimiek. Vytvorme si kalkulačku. V prípade, že používateľ nezadá číslo alebo sa pokúsi deliť nulou, zachytíme výnimku a vypíšeme používateľovi chybu.
Logika kalkulačky
Vytvorme si súbor calculator.py s triedou
Calculator, ktorá bude obsahovať potrebné výpočty ako
metódy:
class Calculator: def add(self, a, b): return a + b def subtract(self, a, b): return a - b def multiply(self, a, b): return a * b def divide(self, a, b): return a / b
Hlavný skript
Komunikáciu s používateľom umiestnime do hlavného skriptu
main.py, odkiaľ budeme ovládať aj objekt
calculator. Používateľa sa opýtame na dve čísla, s ktorými
bude chcieť počítať. Celú logiku zadávania vstupu od používateľa dáme
do bloku try. Teda keď nastane chyba typu ValueError,
program skočí do bloku except a vypíše chybu:
from calculator import Calculator calculator = Calculator() try: a = float(input("Enter the first number: ")) b = float(input("Enter the second number: ")) except ValueError: print("Error: The input is not a number.")
Vždy je najlepšie dávať do bloku try iba tú
časť kódu, ktorá môže vyvolať chybu. Ďalej sa odporúča zachytávať
určitý typ výnimky. Pri porušení jedného z týchto bodov zvyšujeme
šancu, že zachytíme výnimku, s ktorou sme nepočítali, a tak môžeme
spôsobiť neočakávané správanie aplikácie.
Zvyšok programu vykonáme vo vetve else, ktorá sa spustí,
keď k chybe nedôjde. Necháme si zadať operáciu a podľa nej potom zavoláme
danú metódu na objekte calculator. Metóda
calculator.divide() môže pri delení nulou vyvolať výnimku, jej
volanie teda vložíme do bloku try a v prípade chyby
(except) chybu vypíšeme:
from calculator import Calculator calculator = Calculator() try: a = float(input("Enter the first number: ")) b = float(input("Enter the second number: ")) except ValueError: print("Error: The input is not a number.") else: operation = input("Choose an operation (+, -, *, /): ") match operation: case "+": result = calculator.add(a, b) case "-": result = calculator.subtract(a, b) case "*": result = calculator.multiply(a, b) case "/": try: result = calculator.divide(a, b) except ZeroDivisionError as e: result = "Error: Cannot divide by zero." case _: result = "Error: Invalid operation." print("Result:", result)
Skúsme program spustiť a zadať neplatný vstup:
Konzolová aplikácia
Enter the first number: one
Error: The input is not a number.
A skúsme deliť nulou:
Konzolová aplikácia
Enter the first number: 10
Enter the second number: 0
Choose an operation (+, -, *, /): /
Result: Error: Cannot divide by zero.
raise
Doteraz sme iba zachytávali chyby, ktoré vyvolal samotný Python
(napríklad delenie nulou). Občas sa nám však hodí výnimku vyvolať
úmyselne, napríklad keď používateľ zadá hodnotu, ktorá je síce
technicky platná, ale pre náš program nedáva zmysel. Na to slúži príkaz
raise.
Ukážeme si to na metóde triedy Calculator, ktorá bude
počítať druhú odmocninu. V Pythone možno odmocniť aj záporné číslo,
ale výsledok je potom komplexné číslo, ktoré sme sa rozhodli v našej
kalkulačke nepodporovať. Preto sa rozhodneme takýto vstup zakázať a
vyvoláme vlastnú výnimku. Doplňme súbor calculator.py o
nasledujúcu metódu:
def square_root(self, a): if a < 0: raise ValueError("The square root of a negative number is not supported") return a ** (1 / 2)
Druhú odmocninu technicky vypočítame umocnením čísla na
jednu polovicu. Rovnako by sme mohli použiť aj matematickú funkciu
sqrt().
Teraz si môžeme v hlavnom programe vyskúšať, ako sa raise
správa. Ak si nechcete prepisovať pôvodný main.py, vytvorte si
napríklad main_square_root.py a budeme spúšťať tento
súbor:
from calculator import Calculator calculator = Calculator() try: number = float(input("Enter a number to calculate its square root: ")) result = calculator.square_root(number) except ValueError as e: result = "Error: No number entered or a negative number entered." print("Result:", result)
Ak zadáme kladné číslo, program bez problémov vypíše odmocninu:
Konzolová aplikácia
Enter a number to calculate its square root: 100
Result: 10.0
Ak zadáme záporné číslo, metóda square_root() pomocou
raise vyvolá výnimku ValueError a program ju
zachytí v except a vypíše zrozumiteľnú chybovú hlášku:
Konzolová aplikácia
Enter a number to calculate its square root: -1
Result: Error: No number entered or a negative number entered.
Zhrnutie lekcie
Výnimky nám umožňujú ošetriť chyby tak, aby program pri nesprávnom
vstupe nespadol, ale zrozumiteľne zareagoval. Rizikový kód zapisujeme do
bloku try a konkrétne chyby zachytávame v blokoch
except, napríklad ako ValueError alebo
ZeroDivisionError. Blok else sa spustí len pri
úspešnom priebehu bez chyby a finally prebehne vždy. Vlastnú
výnimku môžeme vyvolať príkazom raise, ak zadaná hodnota pre
náš program nedáva zmysel.
V nasledujúcej lekcii, Vlastnosti v Pythone, sa budeme zaoberať vlastnosťami čiže gettermi a settermi, ktoré umožnia jednoduchšie nastavovanie a validáciu hodnôt atribútov.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 0x (2.6 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Python
