Hungarian (Magyar) translation by Peter Matyus-Jarai (you can also view the original English article)
Amikor a debuggolás szóba kerül, akkor az azt jelenti, hogy bug lehet a kódunkban. Nos, nem arra a bogárra (bug) gondolok, ami a házban mászkál - hanem itt egy programkód hibára (bug).
Mielőtt tovább mennénk ezzel a tutoriallal, tisztázzunk néhány alapfogalmat. Röviden definiáljuk, hogy mit értünk bug és debuggolás alatt.
Bugok
Egy bug a számítástechnikában előfordulhat szoftverben és hardverben egyaránt, de mi most itt a szoftverre fókuszálunk. Had említsek meg egy mondát, hogy a bug kifejezés honnan származhat. Úgy tartják, hogy a számítástechnikában akkor használták először a bug kifejezést, amikor egy igazi bogarat (egy molylepkét) találtak a Mark II számítógép egyik reléjében. A bug kifejezést a technikai malőrökre is használták a 19. század végén.
A szoftver bugok nem várt viselkedést okoznak a programokban. Ezzel a kifejezéssel főként egy hibára utalunk, aminek nem tudni a helyét és az okát és súlyos problémákat okozhatnak (pl. leáll a program).
Egy ilyen szituációban debuggolásra van szükségünk.
Debuggolás
Nos, azt mondhatnánk, hogy a problémák elkerülésének a legjobb módja, ha első körben nem írunk bugokat. De sajnos ez eléggé ritka eset és nem könnyű már a kezdetektől kezdve tiszta programot írni. Az, hogy bugjaink vannak, egy normális dolog, amivel biztos találkozni fogunk.
A debuggolás az a folyamat, aminek során megtalálunk, analizálunk és kijavítunk valamilyen bugot (hibát) amivel találkozunk. A debuggolás végső célja, hogy ezeket a bugokat eltávolítsuk, és olyan programot készítsünk ami a szándékunk szerint működik. Fontos megjegyezni, hogy az időnk nagy része arra fog elmenni, hogy megtaláljuk a bugot, mivel ahogy korábban említettük, valójában nem tudjuk hol van a kódban.
Hogy fogalmunk legyen arról, mennyire bonyolult lehet a debuggolás, lássuk mit mondott erről Brian W. Kernighan:
Mindenki tudja, hogy a debuggolás kétszer olyan nehéz, mint először megírni egy programot. Tehát ha a legokosabb állapotodban írod meg a programot, akkor hogy leszel képes egyáltalán debugolni?
Python Kivételek kezelése
A kivétel az egy olyan objektum, ami azt jelzi, hogy egy buggal (hiba) van dolgunk. Más szavakkal, a Python kivételeket használ annak érdekében hogy jelezze, bugok vannak a programban. Ez lenne a lokalizációs része a debuggolási folyamatnak. A kivétel objektum fogadását és a szükséges feladatok végrehajtását a buggal kapcsolatban, a kivétel kezelésének nevezzük. Ezek lennének az analizáló és javító lépések a debuggolási folyamatban.
A try utasítás
A Python try
utasítását használjuk a kivételek kezelésére. Két formája van: try/except
és try/finally
. Az első esetben a try
blokkot egy vagy több except
blokk követheti, míg az utóbbi esetben, a try után csak egy finally
blokk lehet.
try/except
A try/except
szintaxisa a következő:
1 |
try: |
2 |
# try block code
|
3 |
except: |
4 |
# except block code
|
A try blokk törzse olyan kódot tartalmaz, ami kivételt dobhat. Abban az esetben, ha egy kivétel generálódott, a blokkban lévő minden további utasítás ki lesz hagyva. Másrészről, az except
blokk tartalmát kivétel kezelőnek hívjuk, mivel ez fogja el a kivételt. Az except blokk kódja csak akkor lesz végrehajtva, ha egy kivétel generálódott, egyébként a blokk ki lesz hagyva. Beépített kivételeket is használhatunk ahogy a Python Standard Library is mutatja.
Lássunk egy példát, hogy világosabb legyen. Tegyük fel, hogy meg kell adnunk egy osztót egy osztáshoz. Mivel nullával nem lehet osztani, írjunk egy try/except
utasítást, ami leellenőrzi hogy az osztó nulla-e, és kiír egy üzenetet, ha ez a hiba történt.
1 |
denominator = input('Enter a denominator value: ') |
2 |
try: |
3 |
formula = 15/denominator |
4 |
print 'The result is ' + str(formula) |
5 |
except ZeroDivisionError: |
6 |
print 'You attempted to divide by zero which is not allowed' |
Ha például 5
-öt adunk meg bemenetként, ezt a kimenetet kapnánk:
1 |
The result is 3 |
Most írjunk be 0
értéket bemenetként. Milyen kimenetet fogunk kapni ebben az esetben?
try/finally
A try/finally
blokk egy másik módja annak, hogy try utasítást írjunk Pythonban. A finally
blokkokat takarító vagy befejező blokkoknak hívják, mivel mindig lefutnak, akár volt kivétel a try
blokkban kezelve, akár nem.
Próbáljuk ki az előző példát a finally
blokkal:
1 |
denominator = input('Enter a denominator value: ') |
2 |
try: |
3 |
formula = 15/denominator |
4 |
print 'The result is ' + str(formula) |
5 |
finally: |
6 |
print 'You attempted to divide by zero which is not allowed' |
Vegyük észre, ha például az 5
-ös értéket adjuk bemenetként, akkor a következő kimentet kapjuk:
1 |
The result is 3 |
2 |
You attempted to divide by zero which is not allowed |
A raise kulcsszó
A raise
kulcsszó egy másik módja a kivételek kezelésének Pythonban. Ennek a segítségével saját kivételeket válthatunk ki - ezek olyan kivételek, amik akkor váltódnak ki, amikor az elvárt hibákon kívül generálunk valamilyen saját eseményt.
Lássunk egy példát a raise
kulcsszó használatára, hogy jobban megérthessük a koncepciót.
1 |
try: |
2 |
x = input('Enter a number in the range 1-10: ') |
3 |
if x<1 or x>10: |
4 |
raise Exception |
5 |
print 'Great! You listened to me and entered a valid number' |
6 |
|
7 |
except: |
8 |
print 'Your number seems to be outside the range 1-10' |
Ebben a példában, ha megengedett tartományon kívül írunk be egy számot, akkor a print
utasítás végrehajtódik az except
blokkban.
Folytassuk, próbáljunk ki néhány értéket, és ellenőrizzük a kimenetét.
A traceback modul
A Python traceback
modulja egy másik módja a kivételek kezelésének Pythonban. Alapvetően arra használjuk, hogy kiírassuk egy program hívási verem listáját (stack trace/backtrace), miután egy kivétel történt. A traceback
tartalmazza a hibaüzenetet, a kód sorszámát, ahol az a hiba történt, és a hívás listát (call stack), amiben az egymás utáni függvény hívások vannak, ami végül a hibához vezet.
Nézzünk egy példát, ami egy traceback
-et generál:
1 |
def createException(name): |
2 |
raise Exception('It seems that ' + name + ' raised an exception') |
3 |
|
4 |
createException('Abder') |
Ha futtatjuk ezt a scriptet, a kimenete így néz ki:
1 |
Traceback (most recent call last): |
2 |
File "test.py", line 4, in <module> |
3 |
createException('Abder') |
4 |
File "test.py", line 2, in createException |
5 |
raise Exception('It seems that ' + name + ' raised an exception') |
6 |
Exception: It seems that Abder raised an exception |
Vegyük észre hogy a bug (hiba) a line 2
sorban történt, a createExeption
függvényben. Vegyük még észre, hogy a hívás lista segít nekünk hogy vissza kövessük melyik hívás vezetett a hibához, ami ebben az esetben az a hívás, ami a line 4
sorban van.
A cikk kezd hosszú lenni, és szeretnék ennél a pontnál megállni. Amint láthattuk, természetes és rendszeres dolog a programokat debuggolni, és úgy gondolom, hogy a hiba típusok amiket ebben a tutorialban láttál, ismerősek voltak, ugye?
Vannak más módszerek is egy Python program debuggolásához és a kivételek kezeléséhez. Egy jól ismert módja például az assert statement
.
Jó debuggolást!