Ugrás a lényegre

Hibák és azok kezelése

TL;DR Tartalom
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.

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.

>>> 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:

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.

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.

>>> 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:

... 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:

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.

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.

>>> raise NameError('HiThere')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: HiThere
>>> 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.

>>> def fv():
... try:
... return True
... finally:
... return False
...
>>> fv()
False