Hibák kezelése
Eddig tökéletes, hibátlan szoftvereket fejlesztettünk, mert ezek egyszerű kis kódok voltak, amik általában nem is függtek olyan adattól amit a felhasználótól kaphattunk. Ezért nem is nagyon volt minek elromlania.
A valódi életben viszont a valami mindig el fog baszódni. Jobb esetben a program futtatása előtt, rosszabb esetben (és általában) futás közben.
Háromféle hiba keletkezhet a programban: szintaktikai, futásidejű és szemantikai (logikai).
Szintaktikai hiba az, amikor a forráskódunk hibás: nem megfelelő a behúzás, elmarad a zárójel, vessző, és ehhez hasonló dolgok, amik megakadályozzák a Pythont hogy elolvassa a forráskódot. Az ilyen hibák nem engedik hogy elinduljon a program, viszont elég jól behatárolhatóak, mert a Python meg tudja mondani, hogy melyik volt az a sor és karakter, ahol valami szokatlan/nem várt parancs állt.
A futásidejű hiba az, amikor a programunk helyesen fut, de aztán egyszer csak valami nem várt esettel találkozik a program. Rengeteg ilyen hiba keletkezhet akkor, ha a felhasználótól várunk adatra. Például felszólítjuk az usert, hogy gépeljen be egy dátumot, de ő nem olyan formátumban teszi ezt meg amire az algoritmust írtunk. Ekkor rövid időn belül hibát jelez a Python, mert mondjuk a begépelt adatban nem annyi számjegy van mint amire számítottunk; kötőjel helyett szóköz van és ezért nem tudjuk a dátumot komponensekre szétbontani. Remélem érezhető: igen nehéz minden esetre felkészülni, de a lényeg, hogy a nem várt adat előbb-utóbb mindenképp megakasztja az algoritmust, amit a Python jó vastag hibaüzenettel ad majd a tudtunkra.
A szemantikai hiba a legtrükkösebb. Ilyenkor a forráskód helyes, viszont a program “nem azt csinálja amit akarunk” (természetesen a program mindig azt és csak is azt csinálja amit a forráskódban leírtunk). Ezeket a hibákat csak akkor tudjuk kijavítani, ha átolvassuk és újra értelmezzük az algoritmusunkat, esetleg teljesen újat írunk ugyan annak a problémának a megoldására. A lényeg, hogy szemantikai hiba miatt nem kapunk majd hibaüzenetet, ezért nagyon nehezen detektálhatóak az ilyen hibák, e miatt igen kártékonyak tudnak lenni (mert csak akkor vesszük észre hogy valami rosszul működik, mire az látható kárt okozott).
A hibákat a hétköznapokban bug-nak szokták hívni.
Szintaktikai hibák
A szintaktikai hibák száma annál kevesebb minél többet programoz az ember, ezért ezekkel csak egy példa erejéig foglalkozunk. Vegyük az alábbi hibás kódot:
print(Hello world)
A probléma hogy a Hello World
nem string, mivel nincs idézőjelek közé téve. Ha futtatjuk a programot, akkor valami ilyesmit kapunk a konzolba:
File "/home/slapec/.PyCharm2016.1/config/scratches/blog.py", line 1
print(Hello world)
^
SyntaxError: invalid syntax
Pythonban ezt a szöveget traceback-nek nevezik. A következő fejezetben részletesen át is nézzük a részeit. Egyelőre viszont elég az utolsó sort olvasni, mert többnyire itt van a lényeg. Ez az esetünkben a SyntaxError: invalid syntax
szöveg. Igen csekély angol tudással is látható, hogy a hibát a helytelen szintaxis okozza. Soronként felfelé haladva látszódik az a részlete a forráskódnak, ahol a hiba érzékelhetővé vált, majd legfelül az is, hogy melyik fájl melyik sorában történt a hiba. Így már csak oda kell menni és ki kell javítani.
Szintaktikai hiba keletkezése
A fenti tracebackben a ^
jellel jelölték, hogy a forráskódban hol keletkezett szintaktikai hiba. Ez a jel a world
szó végére mutat. Ez nem véletlenül van így: a Hello
szónál nem beszélünk még hibáról, hisz a Hello
idézőjelek nélkül akár értelmezhető lehetne változóként is. Viszont a függvény argumentumai között vesszőnek kell állnia, ami hiányzik. A forráskód értelmezése eljut függvény hívásának végéig, így biztossá válik, hogy már nem is lesz vessző az argumentumok között, így tehát a world
szó az, amire nem számít a Python, és létrejön a SyntaxError
.
A mesének az a lényege, hogy a Python mindig azt a pontot mutatja meg, ahol már biztos hogy hibás a szintaxis. Előfordulhat, hogy ez sorokkal később válik csak nyilvánvalóvá:
print(int('10')
Itt lemaradt a print()
bezáró zárójele. A következő tracebacket kapjuk:
File "/home/slapec/.PyCharm2016.1/config/scratches/blog.py", line 2
^
SyntaxError: unexpected EOF while parsing
Bizony, ez a nagy büdös semmire mutat. Az unexpected EOF while parsing
üzenet azt jelenti, hogy korábban lett vége a fájlnak mint amire a Python számított (Az EOF az End Of File kifejezés rövidítése).
Ez azért történhetett, mert a Python a print()
lezáró zárójelét keresete, de közben véget ért a fájl, így az már sose lesz meg.
Szemantikai hibák
A szemantikai (logikai) hibák úgy kerülhetőek el a legkönnyebben, ha nem írunk rossz kódot. Na persze, ezt aztán baromi könnyű mondani, de megcsinálni azért már nem annyira.
Gondos tervezéssel és megfelelő teszteléssel kellően jól megbizonyosodhatunk róla hogy az algoritmusunk jól működik. A forráskód tesztelésére is kínál eszközöket a Python, de egyelőre nem foglalkozunk ezeknek a használatával, mert arról megint egy jó vastag bejegyzésre való szöveget össze lehetne hordani.
Egyelőre tehát igyekezzünk jó algoritmusokat írni, és keressük a hibákat végig a fejlesztés során. Azaz készüljön el a program egy kisebb része, próbáljuk ki hogy megfelelően működik-e, majd folytassuk az építkezést. Így még a program alapjainál kiderülhet ha valami rosszul működik.
Ha beütött a baj, és látszólag minden megfelelőnek tűnik, akkor jöhetnek az úgynevezett debugger programok. Pythonban ilyenkor a program futása minden soron megáll, és megvizsgálhatjuk a memória tartalmát, láthatjuk hogy a program egy elágazásban milyen irányba fog haladni, és egyéb érdekes dolgok.
Szemantikai hibák keletkezése
Vegyünk egy tipikus logikai hibát, amitől a programunk végtelen ciklusba fog kerülni:
i = 0
while i != 10:
print(i)
A probléma az, hogy elfelejtettük növeli az i
változó értékét, így sosem fog a program kilépni a ciklusból.
A fenti példa még elég triviális, a következő viszont már nem biztos:
i = 0
while i != 10:
print(i)
i += 0.1
Ebben a kis kódban 0.1
-esével növeljük az i
változót, amíg az el nem éri a 10-et. Valamiért azonban mégis átugorja a Python a feltételt és elkezd számolni mint a barom felfelé.
Ha sikerül elkapni az első pár számot ami a konzolba kerül, akkor talán beugrik valami:
0
0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999
1.0999999999999999
A float
típusnál említettem, hogy a lebegőpontos számok pontossága nem végtelen. Pontosan e miatt történt a baj is: összeadódnak a törtek hibái, és ezért az i
változóban levő tört sose lesz majd pontosan 10.
Futásidejű hibák
Igazából az egész bejegyzésnek a fő témája a futásidejű hibák kezelése.
A programozás során kétféleképp győződhetünk meg róla, hogy nem okoz-e hibát az algoritmusunk: először megnézzük hogy szabad-e elvégezni a műveletet és utána végrehajtjuk, vagy először végrehajtjuk és utólag kezeljük a hibát ha keletkezett.
Az előbbi módszert LBYL-nek (Look before you leap (Először gondolkodj, aztán cselekedj)), az utóbbit EAFP-nek (Easier to ask for forgiveness than permission (Könnyebb bocsánatot kérni mint engedélyt)) nevezik.
A Python nyelvben mindkét filozófia megvalósítható, de a nyelv készítői az utóbbi megoldást javasolják.
Személy szerint eléggé keverten használom a két módszert.
Futásidejű hiba keletkezése
Vegyük a korábban felvázolt problémát: kérjük be a felhasználótól a mai dátumot a következő formátumban: ÉÉÉÉ-HH-NN (év, hónap, nap, számokkal, kötőjellel elválasztva), és írjuk vissza a konzolba a magyar helyesírásnak megfelelően.
months = {
'01': 'január',
'02': 'február',
'04': 'március',
'05': 'április',
'06': 'június',
'07': 'július',
'08': 'augusztus',
'09': 'szeptember',
'10': 'október',
'11': 'november',
'12': 'december'
}
today = input('A mai dátum: ')
parts = today.split('-')
year, month, day = parts
month_text = months[month]
print('{0}. {1} {2}.'.format(year, month_text, day))
Ahhoz hogy a számjegyekkel felírt hónapot magyar szavakra átalakítsuk felsoroltam az összes hónapot a months
dict
-ben. Arra számítok hogy ha az aktuális hónap egy számjegyű akkor a bal oldalára nullát írnak majd. A kulcsok azért str
-ek és nem int
-ek, mert így megspóroltam a begépelt hónap int
-é alakítását.
Akkor futtassuk a programot és íruk be pl hogy 2016-04-10:
A mai dátum: 2016-04-10
2016. március 10.
Ez bizony elég szépen ment. Akkor most gépeljük be a dátumot de kötőjelek helyett pontokkal, így: 2016.04.10.
A mai dátum: 2016.04.10.
Traceback (most recent call last):
File "/home/slapec/.PyCharm2016.1/config/scratches/blog.py", line 18, in <module>
year, month, day = parts
ValueError: not enough values to unpack (expected 3, got 1)
Meg is érkeztünk, ez bizony elég szépen meghalt. Kezdjük a tűzoltást a hibaüzenet értelmezésével.
A traceback értelmezése
Szerintem a Python nagyon jó és informatív üzenetet ad hiba esetén. Végigkövethető benne a hiba teljes útvonala egész addig amíg az össze nem omlasztotta a programot.
A traceback két részből áll: a legutolsó sora mutatja a hiba típusát, és a hozzá tartozó rövid hibaüzenetet. A fenti példában tehát ez az:
ValueError: not enough values to unpack (expected 3, got 1)
A hiba típusa a kettőspontig tart, ami ebben az esetben a ValueError
. Ez nem csak egy egyszerű szó, hanem egy konkrét Python osztály megnevezése, de egyelőre még hívjuk csak típusnak. Több ilyen típus is található beépítve a Pythonban.
A kettőspont után következik maga a hibaüzenet. Ez általában valamilyen angol mondat, nálunk most ez: not enough values to unpack (expected 3, got 1).
Az üzenet azt jelenti, hogy nincs elég elem amit unpack-elni lehetne (3 kéne de csak 1 van). Ezt a problémát mindjárt orvosoljuk, de előbb vegyük a traceback többi részét.
A hibaüzenet feletti sorok ezek voltak:
Traceback (most recent call last):
File "/home/slapec/.PyCharm2016.1/config/scratches/blog.py", line 18, in <module>
year, month, day = parts
Itt látható hogy melyik fájlban ("/home/slapec/.PyCharm2016.1/config/scratches/blog.py"
), melyik sorban (18
), melyik modulban (<module>
) történt a hiba, alatta pedig az a konkrét sora a forráskódnak, ahol a hiba létrejött.
A <module>
ebben az esetben azt jelenti, hogy közvetlenül a folyó forráskódban volta a hiba.
Ez egy elég rövid kis traceback volt, mivel a hiba nem valamelyik függvény (vagy más egyéb struktúra) mélyén keletkezett. Írjuk át kicsit a kódot, hogy vastagabb hibaüzenetet is lássunk:
def get_month(month):
months = {
'01': 'január',
'02': 'február',
'04': 'március',
'05': 'április',
'06': 'június',
'07': 'július',
'08': 'augusztus',
'09': 'szeptember',
'10': 'október',
'11': 'november',
'12': 'december'
}
return months[month]
def pretty_date(today):
parts = today.split('-')
year, month, day = parts
month_text = get_month(month)
return '{0}. {1} {2}.'.format(year, month_text, day)
today = input('A mai dátum: ')
print(pretty_date(today))
Annyi változtatás történt, hogy a hónap átalakítása, és a magyar formátumra alakítás egy-egy függvénybe került (get_month()
és pretty_date()
). Vegyük észre, hogy a pretty_date()
hívja majd meg a get_month()
-ot.
Most írjuk be a dátumot például így: 2014-4-10.
A mai dátum: 2016-4-10
Traceback (most recent call last):
File "/home/slapec/.PyCharm2016.1/config/scratches/blog.py", line 27, in <module>
print(pretty_date(today))
File "/home/slapec/.PyCharm2016.1/config/scratches/blog.py", line 21, in pretty_date
month_text = get_month(month)
File "/home/slapec/.PyCharm2016.1/config/scratches/blog.py", line 16, in get_month
return months[month]
KeyError: '4'
Ez rögtön érdekesebben néz ki. A hiba típusa most a KeyError
. Ilyet akkor kapunk ha nem létező kulcsot próbálunk elérni egy dict
-ben. A hibaüzenet egyszerűen annyi hogy '4'
. Így össze is áll a kép: a '4'
kulcs valahonnan hiányzik. Mindjárt az is meglesz hogy honnan.
Láthatóan 3 sor tartalmaz fájlnevet, de ezek mind ugyan arra a fájlra mutatnak. Általában elmondható, hogy ezeket a sorokat lentről-felfelé érdemes olvasni. Ha így haladunk, akkor legelőször azt a sort látjuk, ahol ténylegesen létrejött a hiba. Ahogy haladunk felfelé, úgy követhetjük hogy a hiba hogyan gyűrűdzik végig a programon.
- A program a 16. sorban létrejött a hiba a
return months[month]
utasításnál. Ez a get_month
modulban (függvényben) van. Így már tiszta is, hogy a months
dict
-ből hiányzott a kulcs.
- Ide úgy jutottunk, hogy a 21. sorban a
month_text = get_month(mont)
-nél meghívtuk a hibázó függvényt. Ez a pretty_date
modulban (függvényben) történt.
- A 21. sorba pedig a 27. sorból ugrottunk. Ez a
<module>
modulban van, tehát minden függvényen kívül.
Jól látható, hogy maga a hiba igen mélyen történt, az mégis egészen addig halad felfelé a programban, amíg a program ki nem lép.
A hiba kezelése az a művelet lesz, amikor ezt a hibát az útja során valahol elkapjuk, hogy ne omlassza össze a programot.
A hiba keletkezését hétköznapian úgy mondjuk hogy az algoritmus hibát dob. Angolul, a Pythonos elnevezéseknek megfelelően ezt úgy mondják, hogy raise.
Az egyértelmű hogy a raise nem azt jelenti hogy dobni. Más programozási nyelvekben a raise helyett a throw kifejezést használják és ennek a szónak a magyar változata épült be a beszédbe.
Hasonlóan, a hibát elkapni fogjuk. Ennek a Pythonos elnevezése az except lesz, ami szintén köszönő viszonyban sincs az elkapni kifejezéssel. Ugyan úgy, az eltérő programozási nyelvekben használt catch kifejezés vált elfogadottá a beszédben.
A hiba kezelése
Azon a ponton ahol létrejött a hiba véget ér a kód futása, és egy hiba objektum (exception) indul felfelé a programban. Ilyenkor különleges állapotba kerül a Python: ha nem kapjuk el a hibát, akkor a hibakezelő algoritmusok kivételével semmilyen kód sem fut tovább, csak az objektum halad felfelé. Ha sehol se kaptuk el a hibát, akkor végül mindenképp kilép a program (így látszódik majd minden sor a traceback-ben amin végighaladt a hiba).
Az algoritmusunkat (illetve annak tetszőleges részét) úgynevezett try blokkba rakva jelezhetjük a Pythonnak, hogy a blokkban előfordulhat hiba. Ha a blokkban hiba történik, akkor a futás automatikusan a hibakezelő ágakra kerül. Itt típusonként különböző módon foglalkozhatunk a hibával. Ha nem volt olyan ág, ahol a hibát lekezeltük volna, akkor a hiba halad tovább felfelé.
A korábbi traceback-ben három sor is látható volt, így jól megbecsülhető, hogy három helyen kaphattuk volna el a hibát. Az egyszerűség kedvéért most a program végén tesszük ezt meg. Lássuk az új struktúrát!
def get_month(month):
months = {
'01': 'január',
'02': 'február',
'04': 'március',
'05': 'április',
'06': 'június',
'07': 'július',
'08': 'augusztus',
'09': 'szeptember',
'10': 'október',
'11': 'november',
'12': 'december'
}
return months[month]
def pretty_date(today):
parts = today.split('-')
year, month, day = parts
month_text = get_month(month)
return '{0}. {1} {2}.'.format(year, month_text, day)
today = input('A mai dátum: ')
try:
print(pretty_date(today))
except KeyError:
print('Hibás hónap!')
Semmi sem változott, az utolsó 4 sor kivételével:
- A
try
-al kezdtük az új blokkot.
- Hiba esetén az
except
sorra ugrik a program. Az utasítás mellé a hiba típusa kerül, aminek bekövetkeztében a program futásának itt kell folytatódnia. Látható, hogy a KeyError
nem string! Másik fontos dolog, hogy ide nem lehet feltételeket tenni, mint az if
esetében.
- Az
except
ágba kerül az a kód, ami KeyError
hiba esetén lefut majd.
Futtassuk így a programot, és írjuk be hogy: 2016-4-10. Így már a Hibás hónap! felirat jelenik meg a konzolban. Ez egyből sokkal barátságosabb.
Most próbáljuk meg a legelső hibás példa szerint begépelni a dátumot, azaz pontokkal elválasztva. Ekkor még mindig hibaüzenet kapunk, mivel ez nem KeyError
típusú hiba volt.
A try
-hoz tetszőleges számú except
adható, így kezelhetjük a ValueError
-t is:
try:
print(pretty_date(today))
except KeyError:
print('Hibás hónap!')
except ValueError:
print('Hibás formátum!')
Innen már egyszerű: ha a try
-ban KeyError
történt akkor az az alatti ágban; ha ValueError
keletkezett akkor meg annak az ágába folytatódik a program.
Lehetséges egy ágban lekezelni több különböző típusú hibát is a típusok felsorolásával:
try:
print(pretty_date(today))
except (KeyError, ValueError):
print('Hibás dátum!')
Bár úgy nézhet ki a zárójel miatt mintha az except
egy függvény lenne, de az továbbra is utasítás mard. Az extra szóköz nyomatékosítja ezt.
A fenti kóddal általánosságban elmondhatjuk, hogy ha a pretty_date()
akár KeyError
akár ValueError
hibát dob, akkor hibás volt a dátum amit begépelt a felhasználó.
Az else
ág
Írjuk át a programot így:
try:
text = pretty_date(today)
except (KeyError, ValueError):
print('Hibás dátum!')
print('A dátum:', text)
A szándék az volt, hogy a try
-ban csak a dátum konvertálását végezzük el. Ha ez sikeres volt, akkor a kiírás is biztos menni fog, így annak felesleges try
-ban maradnia.
Ha helyes dátumot írunk be, akkor minden a számításaink szerint zajlik majd. De ha hibásan:
Hibás dátum!
Traceback (most recent call last):
File "/home/slapec/.PyCharm2016.1/config/scratches/blog.py", line 33, in <module>
print('A dátum:', text)
NameError: name 'text' is not defined
Akkor csak egy jóféle NameError
exceptiont kapunk csak. Ez azért történt, mert a text
változót a try
ágban deklaráltuk. A hiba miatt viszont a deklaráció nem történt meg, így a try
-on kívül nem létező változót próbáltunk meg kiírni.
Ezt többféleképp is elkerülhetjük, de talán a legjobb megoldás az, ha az else
ágát használjuk:
try:
text = pretty_date(today)
except (KeyError, ValueError):
print('Hibás dátum!')
else:
print('A dátum:', text)
Az else
igazából az except
-el van kapcsolatban: KeyError
vagy ValueError
esetén fusson az except
ág, különben fusson az else
ág. Tehát ebben az ágban van az a kód, amivel folytatni kell a programot ha nem volt hiba.
A finally
ág
Az utolsó ág ami a try
-hoz tartozik a finally
. Az ebben álló kód mindenképp lefut amikor a program futása elhagyja a try
blokkot, akár volt hiba, akár nem.
Ide általában cleanup kódot szoktak tenni, például bezárják a nyitott fájlokat, vagy kiírnak valami üzenetet mielőtt elhalálozik a program.
Mivel még nem tudjuk hogy hogyan kell fájlba írni, ezért innen most hiányzik a példa.
A nagyon nem várt hiba
A fenti algoritmust végülis egész jól körbebástyáztuk. A komplex programokban könnyen előfordul, hogy bár egy csomó esetre felkészültünk, valamiért mégis olyan hibát kapunk, amire aztán egyáltalán nem számítottunk.
A beépített hiba típusok hierarchikus elrendezésűek, azaz a hierarchia alján álló típusokra minden igaz ami a felettük álló típusokra (öröklik azok tulajdonságait). Ennek a hierarchiának a tetején az Exception
típus áll. Azaz ha ezt a típusú hibát kapjuk el, akkor tényleg minden hibát le tudunk kezelni:
try:
print(pretty_date(today))
except Exception:
print('Hibás dátum!')
Opcionálisan így rövidíthető a fenti kód:
try:
print(pretty_date(today))
except:
print('Hibás dátum!')
Egyes esetekben elvárt, hogy a program semmilyen körülmények között se álljon le, viszont az ilyen hibakezeléssel azt kockáztatjuk, hogy az amúgy igen súlyos fennakadásokról sose kapunk majd tájékoztatást.
Saját hiba készítése
Nem csak a Pythontól várhatunk hibákat, hanem saját magunk is eldobhatunk exception-öket amiket valahol máshol elkaphatunk. Ez többek között függvényekben jöhet nagyon jól: így hibával jelezhetjük, ha nem megfelelő értékeket kaptunk.
Írjunk egy nagyon egyszerű kis függvényt, ami kizárólag pozitív számokat adhat össze:
def add(a, b):
if a >= 0 and b >= 0:
return a + b
else:
raise ValueError('A paramétereknek 0-nak vagy annál nagyobbnak kell lenniük')
Az 5. sorban látható az újdonság, a raise
. Ezzel az utasítással egy exception objektumot dobhatunk el, magyarul így tudunk hibát létrehozni. Itt ugyan azt a ValueError
-t használtam, mint amit korábban a hibás formátumú dátumnál elkaptunk.
A ValueError
-t majdnem úgy kell használni mint egy függvényt, csak ez igazából egy osztály. Régóta kerülgetjük már az osztály fogalmát, pár rész és végre tényleg megdumáljuk hogy mik is azok valójában.
Ha megfelelő, tehát 0 vagy annál nagyobb argumentummal hívjuk meg a függvényt akkor minden rendben lesz. Ha valamelyik argumentum viszont negatív, például így:
add(-5, 10)
Akkor ezt a csinos hibaüzenetet kapjuk:
Traceback (most recent call last):
File "/home/slapec/.PyCharm2016.1/config/scratches/blog.py", line 8, in <module>
add(-5, 10)
File "/home/slapec/.PyCharm2016.1/config/scratches/blog.py", line 5, in add
raise ValueError('A paramétereknek 0-nak vagy annál nagyobbnak kell lenniük')
ValueError: A paramétereknek 0-nak vagy annál nagyobbnak kell lenniük
Őszintén megmondom, igen csinos ez a kis üzenet. Innentől már csak rajtunk áll, hogy hol-milyen hibákat akarunk eldobálni.
Természetesen nem csak a ValueError
használható; itt van a korábban látott KeyError
is, és még egy csomó más típust tartalmaz beépítve a Python, de a legjobb hír az, hogy később majd mi is fogunk teljesen saját hiba típusokat létrehozni.
Az üres utasítás
Levezetésnek következzen egy új utasítás, amiről idáig nem volt szó: a pass
.
Pythonban nem hagyhatunk üresen blokkokat, de van amikor mégis erre lenne szükség: például hiba esetén egyszerűen ne csináljunk semmit. Ekkor használható a pass
utasítás. Ez az utasítás a szó szoros értelmében nem csinál semmit, csak járattatja a processzort. Tölteléknek használható.
Vegyük elő újra a dátum beolvasós példát. Írjuk át úgy, hogy ha hiba történik, akkor szépen csöndben lépjünk ki minden felhajtás nélkül:
def get_month(month):
months = {
'01': 'január',
'02': 'február',
'04': 'március',
'05': 'április',
'06': 'június',
'07': 'július',
'08': 'augusztus',
'09': 'szeptember',
'10': 'október',
'11': 'november',
'12': 'december'
}
return months[month]
def pretty_date(today):
parts = today.split('-')
year, month, day = parts
month_text = get_month(month)
return '{0}. {1} {2}.'.format(year, month_text, day)
today = input('A mai dátum: ')
try:
print(pretty_date(today))
except (KeyError, ValueError):
pass
A legutolsó sorban van a lényeg. A pass
akárhol használható egyébként (függvényben, ciklusban, stb) de csak akkor van értelme használni, ha önmagában áll, máskülönben akármilyen más utasítás behelyettesíthető a helyére.
Függvényben akkor szokták használni, ha a függvény neve már megvan, de az algoritmus még nincs. Ilyenkor hogy a függvény hívható legyen egy pass
utasítást tesznek a törzsébe és később írják meg a kódot a helyére.
Utolsó példa
Írjuk át úgy a fenti kódot, hogy a program próbáljon meg újra dátumot beolvasni ha hiba történt.
while True:
today = input('A mai dátum: ')
try:
print(pretty_date(today))
break
except (KeyError, ValueError):
print('Hibás dátum!')
A végtelenségig várjuk a begépelt szöveget és majd a 6. sorban ugrunk ki a ciklusból. Az 5. sorban megpróbáljuk átalakítani a dátum átalakítását. Ha ezen a ponton hiba történik akkor a futás az except
ágra ugrik. Itt nem állítjuk meg a ciklust, így az újra indul majd.
Ha viszont nem volt hiba, akkor a dátum kiírása után a program 6. sorral folytatódik, ahol a break
utasítás kiléptet a ciklusból. Ilyen egyszerű.
Zárás
Azt hittem hogy ez a bejegyzés nem lesz bazi hosszú, és hogy még a modulokra is lesz idő. Ehhez képest már majdnem 20.000 karakternél járok, úgyhogy jobb is itt befejezni ezt a témát.
A következő részben tényleg jönnek a modulok, és remélhetőleg végre fájlba is fogunk írni.
Ez a bejegyzés a Python tutorialom egyik része. Az összes rész listája itt fellelhető.
-slp