# Hibák és azok kezelése :::tip TL;DR Tartalom - [Hibák általánosságban](#hibák-általánosságban) - Objektumok, példák - [Hibakezelés](#hibakezelés) - [Saját hiba osztályok](#saját-hiba-osztályok) - Ugyanolyan osztály - [try ... catch ...](#try--catch-) - Dobunk és elkapunk hibát - [else](#else) - Semmi hiba nem volt, csinálj valamit - [raise](#raise) - Hibával dobálózás - [finally](#finally) - Még a returnt is felülírjuk :::tip :::info Extra feladatok _Ezek nem kötelező feladatok, csak megoldásuk közben könyebb megtanulni a dolgokat_ - Készíts egy saját hiba osztályt, melyben letárolsz egy számot és híváskor kiírja azt. (Tipp: `__init__`, `__str__`) - Imént definiált hibát kapd el, irasd ki és ne hagyd miatta leállni a programot. :::info ## Hibák általánosságban Python, mint magasszintű nyelv hibák dobására és azok kezelésére is képes. Ezek olyan objektumok, melyekkel a program futásának vezérlési szerkezetét tudjuk megszakítani, majd valahol lekezelni őket. Alapvetően ha nem kerülnek lekezelésre, akkor a futás megáll és a hibát kiírja nekünk az interpeter. A leggyakoribb hiba, amivel a Python tanulása közben fogsz találkozni, az a SyntaxError. ```python >>> while True print('Hello world') File "<stdin>", line 1 while True print('Hello world') ^ SyntaxError: invalid syntax ``` Valamennyire próbál neked segíteni a fordító mikor ilyen keletkezik. Még egy pár hiba: ```python Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: division by zero >>> 4 + spam*3 Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'spam' is not defined >>> '2' + 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Can't convert 'int' object to str implicitly ``` ## Hibakezelés ### Saját hiba osztályok Tudunk készíteni saját hibákat. Ehhez csak egy osztályt kell készítenünk. ```python class ForgovillaHiba(Exception): # Leszármazik az Exceptionből """Valami baj van a forgóvillával""" pass # sad SCH noises ``` ### try ... catch ... `try` és `except` kulcsszavakkal eltudjuk kapni a különböző hibáinkat. ```python >>> while True: ... try: ... x = int(input("Adj meg egy számot: ")) ... break ... except ValueError: ... print("Ez nem egy szám...") ... ``` A `try`-on belüli részen ha keletkezik bármilyen hiba, akkor azonnal tovább dobja az `except`-hez. Itt definiálhatjuk, hogy milyen típusú hibát szeretnénk elkapni. Akár többet is elkaphatunk egyben: ```python ... except (RuntimeError, TypeError, NameError): ... pass ``` Az `except` részben definiált osztályok akkor kapják el az adott hibát, ha kompatibilisek a dobott hibával. Tanulmányozd, hogy mit dob ez esetben a kód: ```python class B(Exception): pass class C(B): pass class D(C): pass for osztaly in [B, C, D]: try: raise osztaly() except D: print("D") except C: print("C") except B: print("B") ``` Különböző dobott hibákat akár le is menthetjük egy változóba, majd annak tartalmával dolgozhatunk. ```python import sys try: f = open('fajl.txt') s = f.readline() i = int(s.strip()) except OSError as err: print("OS error: {0}".format(err)) except ValueError: print("Nem sikerült intbe konvertálni.") except: # Minden más print("Váratlan hiba:", sys.exc_info()[0]) raise ``` ### else Egy `try`, `catch` blokk legvégére tehetünk egy `else`-t, hogy lefuttasunk valamit ha nem történt semmi hiba. ### raise Mi is tudunk hibákat dobni a `raise` kulcsszó segítségével. ```python >>> raise NameError('HiThere') Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: HiThere ``` ```python >>> try: ... raise NameError('HiThere') ... except NameError: ... print('Egy hiba történt!') ... raise ... 'Egy hiba történt!' Traceback (most recent call last): File "<stdin>", line 2, in <module> NameError: HiThere ``` ### finally Végül pedig a `try` lefutása után tudunk definiálni még lépéseket. Az itt definiált dolgok mindenképp lefognak futni, ha volt, ha nem volt hiba. ```python >>> def fv(): ... try: ... return True ... finally: ... return False ... >>> fv() False ```