Informatika2-2015/Eloadas 5 Python-5 Meg referenciak Hibakezeles

A MathWikiből
(Változatok közti eltérés)
 
(egy szerkesztő 3 közbeeső változata nincs mutatva)
35. sor: 35. sor:
  
 
vagy
 
vagy
 +
 
<wikiframe width="950" height="600" frameborder="1" src="http://pythontutor.com/iframe-embed.html#code=fa+%3D+%5B%5B%5B1%5D,+%5B2%5D,+%5B3%5D%5D,+%5B%5B4%5D,+%5B5%5D%5D%5D%0A%0Aprint+fa%0A%0Ajobb_ag+%3D+fa%5B1%5D%0Adel+fa%5B1%5D%0Afa%5B0%5D.append(jobb_ag)%0A%0Aprint+fa&origin=opt-frontend.js&cumulative=false&heapPrimitives=false&textReferences=false&py=2&rawInputLstJSON=%5B%5D&curInstr=0&codeDivWidth=350&codeDivHeight=400"/>
 
<wikiframe width="950" height="600" frameborder="1" src="http://pythontutor.com/iframe-embed.html#code=fa+%3D+%5B%5B%5B1%5D,+%5B2%5D,+%5B3%5D%5D,+%5B%5B4%5D,+%5B5%5D%5D%5D%0A%0Aprint+fa%0A%0Ajobb_ag+%3D+fa%5B1%5D%0Adel+fa%5B1%5D%0Afa%5B0%5D.append(jobb_ag)%0A%0Aprint+fa&origin=opt-frontend.js&cumulative=false&heapPrimitives=false&textReferences=false&py=2&rawInputLstJSON=%5B%5D&curInstr=0&codeDivWidth=350&codeDivHeight=400"/>
 
[http://pythontutor.com/visualize.html#code=fa+%3D+%5B%5B%5B1%5D,+%5B2%5D,+%5B3%5D%5D,+%5B%5B4%5D,+%5B5%5D%5D%5D%0A%0Aprint+fa%0A%0Ajobb_ag+%3D+fa%5B1%5D%0Adel+fa%5B1%5D%0Afa%5B0%5D.append(jobb_ag)%0A%0Aprint+fa&mode=display&origin=opt-frontend.js&cumulative=false&heapPrimitives=false&textReferences=false&py=2&rawInputLstJSON=%5B%5D&curInstr=0 link]
 
[http://pythontutor.com/visualize.html#code=fa+%3D+%5B%5B%5B1%5D,+%5B2%5D,+%5B3%5D%5D,+%5B%5B4%5D,+%5B5%5D%5D%5D%0A%0Aprint+fa%0A%0Ajobb_ag+%3D+fa%5B1%5D%0Adel+fa%5B1%5D%0Afa%5B0%5D.append(jobb_ag)%0A%0Aprint+fa&mode=display&origin=opt-frontend.js&cumulative=false&heapPrimitives=false&textReferences=false&py=2&rawInputLstJSON=%5B%5D&curInstr=0 link]
116. sor: 117. sor:
 
print szulinap</python>
 
print szulinap</python>
  
Így legalább nem mélyül a kód egyre bejlebb, de kevésbé látszik hogy a végén levő kód csak bizonyos esetekben fut le. Bár a bizonyos esetek az (elvileg ritka) hibás esetek, ezért ez annyira nem baj.
+
Így legalább nem mélyül a kód egyre beljebb, de kevésbé látszik hogy a végén levő kód csak bizonyos esetekben fut le. Bár a bizonyos esetek az (elvileg ritka) hibás esetek, ezért ez annyira nem baj.
  
Viszont továbbra is olyan ellenőrzéseket végzünk, amiket már a python elvégezne magától is, és még nem is sikerült minden rossz esetet kezelnünk, kipróbálhatjuk mi történik, ha azt adjuk meg hónapnak, hogy "Február".
+
Viszont továbbra is olyan ellenőrzéseket végzünk, amiket már a python elvégezne magától is, és még nem is sikerült minden rossz esetet kezelnünk, kipróbálhatjuk mi történik, ha azt adjuk meg hónapnak, hogy "Február". Így tehát a manuális hibakezelés hátrányai többek között:
 +
* Sokszor olyan ellenőrzéseket végzünk amit a python beépített függvényei is elvégeznek
 +
* Nehéz minden hibaesetre gondolni, könnyű kifelejteni néhányat
 +
* Mivel azonos a szintaxis a kód egyéb részeivel, nehéz megállapítani ránézésre hogy a kód mely része foglalkozik hibakezeléssel
  
 
== Kivételek ==
 
== Kivételek ==
189. sor: 193. sor:
 
     # Kepzeljuk ide hogy fajlba is kiirja</python>
 
     # Kepzeljuk ide hogy fajlba is kiirja</python>
  
Végső kód minden kijavítása után:
+
Ha az előzőekben írtaknak megfelelően beteszünk egy ''try-except'' részt a fő kódba, akkor így néz ki:
  
 
<python>import datetime
 
<python>import datetime
200. sor: 204. sor:
 
      
 
      
 
def nev_azonosito(nev, nevek):
 
def nev_azonosito(nev, nevek):
     for i in range(len(nevek)):
+
     i = 1
 +
    while i <= len(nevek):
 
         if nevek[i] == nev:
 
         if nevek[i] == nev:
 
             return i
 
             return i
208. sor: 213. sor:
 
     nev = raw_input("Neved? ")
 
     nev = raw_input("Neved? ")
 
     azonosito = nev_azonosito(nev, nevek)
 
     azonosito = nev_azonosito(nev, nevek)
    if azonosito == None:
 
        raise ValueError('Nem ismert nev')
 
 
     szulinap = datum_beolvas()
 
     szulinap = datum_beolvas()
 
     szulinapok[azonosito] = szulinap
 
     szulinapok[azonosito] = szulinap
221. sor: 224. sor:
 
         print nevek
 
         print nevek
 
         print szulinapok
 
         print szulinapok
        # Kepzeljuk ide hogy fajlba is kiirja
+
     except:
     except ValueError as e:
+
         print "Hibas bemenet!"
         print "Sikertelen nev valtoztatas! Hibauzenet:"
+
    # Kepzeljuk ide hogy fajlba is kiirja</python>
        print e</python>
+
  
= Iterátorok =
+
Egyrészt figyeljük meg ezen a kódon, hogy ugyan a függvényeken belül történik a hiba, a függvényeken kívüli ''try-except'' is el tudja azt kapni. A másik dolog amit láthatunk, ha ezt kipróbálgatjuk, hogy ugyan a kódban van egy programozási hiba is (a ''nev_azonosito'' rosszul megy végig a listán), azt is elkapja a hibakezelésünk, és úgy jelzi mintha rossz bemenet lenne, ezzel összezavarva a felhasználót.
  
Gondolkoztatok már rajta, hogy hogy működik a ''for'' ciklus? Itt a kitűnő alkalom!
+
Itt használható az, hogy az ''except'' parancsnak meg lehet adni, hogy csak a kivételek bizonyos típusát kezelje, a többivel ne foglalkozzon. Ha olyan kivétel érkezik, ami nem felel meg az ''except'' leírásának, akkor az lép ki tovább a függvényekből, esetleg eljutva odáig hogy a felhasználó által is látható hibaüzenet lesz belőle, de ez is jobb mint ha rosszul kezelnénk. Ezért ebben az esetben csak a ''ValueError'' típusú hibákat akarjuk elkapni, mert azokról tudjuk hogy a felhasználó által megadott rossz adat okozza. És ha a hibaskezelésünk csak azzal foglalkozik, így már könnyebben megtaláljuk a programozási hibát is.
  
Python-ban for ciklussal sokféle elemen végig lehet menni. Néhány példa:
+
Végső kód kijavított hibával, ami csak a felhasználói hibákat jelzi:
  
<python>lista = [5, 6, 7]
+
<python>import datetime
  
for elem in lista:
+
def datum_beolvas():
     print elem
+
     ev = int(raw_input("Szuletesed eve? "))
 +
    honap = int(raw_input("Honapja? "))
 +
    nap = int(raw_input("Napja? "))
 +
    return datetime.date(ev, honap, nap)
 
      
 
      
szotar = {5: 15, 6: 16, 7 : 17}
+
def nev_azonosito(nev, nevek):
 +
    for i in range(len(nevek)):
 +
        if nevek[i] == nev:
 +
            return i
  
for kulcs in szotar:
+
def szulinap_atir(nevek, szulinapok):
     print kulcs
+
     nev = raw_input("Neved? ")
 +
    azonosito = nev_azonosito(nev, nevek)
 +
    szulinap = datum_beolvas()
 +
    szulinapok[azonosito] = szulinap
 
      
 
      
file = open("tesztfile.txt", "r")
+
nevek = ["nyuszi", "roka", "farkas"]
 
+
szulinapok = [datetime.date(1, 1, 1) for i in range(3)]
for sor in file:
+
    print sor</python>
+
  
Mindegyik esetben vannak speciális módszerek amivel ''for'' nélkül is megoldható a dolog, de későbbi dolgokhoz fontos hogy megértsük, hogy hogy működik a dolog. Ehhez kell egy speciális osztály fajta, az iterátor. Itt van, hogy hogy néz ki ugyanaz a kód iterátorral és for-ral:
+
while True:
 
+
    try:
<wikiframe width="950" height="600" frameborder="1" src="http://pythontutor.com/iframe-embed.html#code=l+%3D+%5B5,+6,+7%5D%0D%0A%0D%0A%23+for-ral%0D%0Afor+elem+in+l%3A%0D%0A++++print+elem%0D%0A%0D%0A%23+Iterator-ral%0D%0Aiterator+%3D+iter(l)%0D%0Atry%3A%0D%0A++++while+True%3A%0D%0A++++++++elem+%3D+iterator.next()%0D%0A++++++++print+elem%0D%0Aexcept+StopIteration%3A%0D%0A++++pass&origin=opt-frontend.js&cumulative=false&heapPrimitives=false&textReferences=false&py=2&rawInputLstJSON=%5B%5D&curInstr=0&codeDivWidth=400&codeDivHeight=400"/>
+
        szulinap_atir(nevek, szulinapok)
[http://pythontutor.com/visualize.html#code=l+%3D+%5B5,+6,+7%5D%0D%0A%0D%0A%23+for-ral%0D%0Afor+elem+in+l%3A%0D%0A++++print+elem%0D%0A%0D%0A%23+Iterator-ral%0D%0Aiterator+%3D+iter(l)%0D%0Atry%3A%0D%0A++++while+True%3A%0D%0A++++++++elem+%3D+iterator.next()%0D%0A++++++++print+elem%0D%0Aexcept+StopIteration%3A%0D%0A++++pass&mode=display&origin=opt-frontend.js&cumulative=false&heapPrimitives=false&textReferences=false&py=2&rawInputLstJSON=%5B%5D&curInstr=0 link]
+
        print nevek
 +
        print szulinapok
 +
    except ValueError as e:
 +
        print "Sikertelen nev valtoztatas! Hibauzenet:"
 +
        print e
 +
    # Kepzeljuk ide hogy fajlba is kiirja</python>

A lap jelenlegi, 2015. március 16., 11:23-kori változata

Tartalomjegyzék

Referenciák még kicsit

Jó paraméter módosítás

Nézzünk egy konkrét példát amikor érdemes kihasználni az objektumok változtathatóságát, hogy referenciákon keresztül férek hozzájuk. A következő példában egy adatbázis bejelentkezését kezelem, és van egy szótáram ami tárolja hogy melyik felhasználónak hány sikertelen belépése volt. Itt egy kódvázlat ami követi az eddigi tanácsaimat, és nem módosít bele paraméterként kapott változóba:

link

Azt láthatjuk, hogy a 8-12 lépéseknél két másolat is van az adatokról, amik nem, vagy csak alig térnek el egymástól. Elképzelhető lenne, ha elég nagy a rendszer, hogy ez a szótár nem csak 3 felhasználót tárol, hanem több ezret. Ezzel egy akár néhány megabyte-os új objektumot hozok létre a memóriában. (Lehet még optimalizálni a kódot, hogy csak akkor másolja le ha tényleg belemódosít, de az most mindegy.)

Azonban, ha nem lesz szükség az eredeti változatra később (és ebben az esetben miért lenne), akkor módosíthatom a paramétert:

link

Amit itt meg kell figyelni, hogy:

  • Le van dokumentálva hogy módosítom a paramétert. (Ha valamelyik felhasználó nem szeretné hogy módosuljon az objektuma, még mindig adhat csak egy másolatot át.)
  • Nincs visszatérési érték. Ez általános módszer annak a jelzésére hogy nem egy módosított változat készült, hanem az eredeti objektum módosult.

Általánosságban pont ezért módosíthatóak az objektumok, mert nagy adathalmazoknál nem engedhető meg mindig másolat készítése. A CloudCoder-ben írt és hasonló gyakorló jellegű feladatok megoldásánál továbbra is azt ajánlom hogy egyik függvényetek se módosítson a paraméterein, hanem csak ha biztosak vagytok benne hogy kell, azt kezeljétek speciális esetként.

Referencia mint mutató

Az a koncepció, hogy az objektumok léteznek a memóriában, attól függetlenül hogy milyen néven hívjuk őket, és a változók csak referenciák amik mutatnak ezekre az objektumokra, segíthet értelmezni a következő kódot:

link

Egészen a 7-es lépésig az a felfogás, hogy ezek a listák egymáson belül vannak, működik teljesen jól. Print-elve is így néz ki, 3 lista egymáson belül. Azonban az utolsó két sor értelmezéséhez el kell felejtenünk ezt az elképzelést. Ez már csak akkor értelmezhető, ha a listáimat egy-egy gráf pontjaiként értelmezem, amik között irányított élek vannak. Egy-egy referencia mutathat egy változóból, vagy egy lista vagy szótár egy eleméből, egy tetszőleges objektumra.

Ez a felfogás mutatja, hogy az ilyen egymásba zárójelezett listák pl. egy faszerkezetet jelképeznek gráfként nézve. Ennek megfelelően manipulálhatóak is:

link

vagy

link

Egyelőre nem kell ezt ilyen műveletekre felhasználnotok, de jó ha elkezdtek átszokni erre a gondolkodásra, mert akkor könnyebb lesz megérteni a programok működését sok esetben.

Hibakezelés

Alap python viselkedés

Nézzük ezt a (hibás) kódot:

link

Ha futtatom ezt a kódot a parancssorból, akkor a következő üzenetet kapom a python-tól:

Traceback (most recent call last):
  File "D:\prog\Info2\teszt\hiba.py", line 8, in <module>
    l2 = listaoszt([5, 10, 15], 0)
  File "D:\prog\Info2\teszt\hiba.py", line 6, in listaoszt
    l[i] = oszt(l[i], b)
  File "D:\prog\Info2\teszt\hiba.py", line 2, in oszt
    return a / b
ZeroDivisionError: integer division or modulo by zero

Már láthattatok ilyesmit ha futtatok a gépeteken kódot (akár Spyder-rel), a CloudCoder is ennek az üzenetnek a végét adja vissza hiba esetén.

Itt lehet látni, hogy kiírja az összes függvényt ami éppen fut a hiba pillanatában, majd a hiba típusát. Ez általában a programozó számára elég sok információ, hogy legalábbis el tudja kezdeni keresni a hiba pontos forrását. Azonban ha a programunknak felhasználója van, számára ez biztos nem barátságos hibaüzenet. Nézzük meg mit tehetünk ezzel.

Hibák típusai

Alapvetően megkülönböztethetünk két fajta hibát ami előfordulhat a programban. Az egyik eset ha a programozó vétett hibát, és a program nem működik jól. A második eset ha a program felhasználója rosszul próbálja használni a programot. Utóbbira példa lehet ha a fentihez hasonlóan egy számológép programban nullával próbál osztani, vagy akár az is ilyen eset ha olyan bejelentkezési nevet/jelszavat ad meg ami nem helyes.

Az első esettel kis programok esetén, akár néhány száz felhasználóig, ha még a felhasználók tudnak közvetlenül szólni a fejlesztőnek, nem kell foglalkoznunk különösebben előre. Úgyis a programozónak kell majd javítani a hibát, így nem baj ha a python "programozó nyelven" mondja meg hogy mi a hiba. A felhasználó szempontjából az a megoldás hogy szól a programozónak hogy "ezt próbáltam csinálni, és akkor a program ezt a furcsa üzenetet adta vissza", és remélhetőleg ez alapján a programozó meg tudja oldani a hibát.

Utóbbi esetben viszont a felhasználó számára az lenne a jó, ha megmondaná neki a program hogy hogy használja rosszul, és ő ki tudná javítani, anélkül hogy szólnia kéne bárki másnak. (És a programozónak is jobb ha nem őt zaklatják minden ilyen esetben, hanem a program elmagyarázza a bajt. Összességében kevesebb munka.) Az ilyen esetet már néhány soros, egyetemi project-ekben használt, egyszerű programoknál is érdemes kezelni ahol nem nagy gond. Ha már legalább egy másik ember elképzelhető hogy használni fogja, vagy akár saját magunk néhány évvel később.

Egyszerű kezelés

Az ilyen problémák kezeléséhez nincsen feltétlenül szükség új technikákra. Lehet például így kezelni:

import datetime
import calendar
 
ev = int(raw_input("Szuletesunk eve? "))
honap = int(raw_input("Honapja? "))
nap = int(raw_input("Napja? "))
 
if (ev < datetime.MINYEAR or ev > datetime.MAXYEAR or
        honap < 0 or honap > 12):
    print "Hibas honap vagy ev!"
else:
    if nap < 0 or nap > calendar.monthrange(ev, honap)[1]:
        print "Hibas nap!"
    else:
        szulinap = datetime.date(ev, honap, nap)
 
        print szulinap

Láthatóan jelentősen nőtt a kód bonyolultsága. Ha nem probléma hogy a hiba hatására kilép a program/függvény akkor még valamivel lehet egyszerűsíteni így:

import datetime
import calendar
 
ev = int(raw_input("Szuletesunk eve? "))
honap = int(raw_input("Honapja? "))
nap = int(raw_input("Napja? "))
 
if (ev < datetime.MINYEAR or ev > datetime.MAXYEAR or
        honap < 0 or honap > 12):
    print "Hibas honap vagy ev!"
    exit()
 
if nap < 0 or nap > calendar.monthrange(ev, honap)[1]:
    print "Hibas nap!"
    exit()
 
szulinap = datetime.date(ev, honap, nap)
 
print szulinap

Így legalább nem mélyül a kód egyre beljebb, de kevésbé látszik hogy a végén levő kód csak bizonyos esetekben fut le. Bár a bizonyos esetek az (elvileg ritka) hibás esetek, ezért ez annyira nem baj.

Viszont továbbra is olyan ellenőrzéseket végzünk, amiket már a python elvégezne magától is, és még nem is sikerült minden rossz esetet kezelnünk, kipróbálhatjuk mi történik, ha azt adjuk meg hónapnak, hogy "Február". Így tehát a manuális hibakezelés hátrányai többek között:

  • Sokszor olyan ellenőrzéseket végzünk amit a python beépített függvényei is elvégeznek
  • Nehéz minden hibaesetre gondolni, könnyű kifelejteni néhányat
  • Mivel azonos a szintaxis a kód egyéb részeivel, nehéz megállapítani ránézésre hogy a kód mely része foglalkozik hibakezeléssel

Kivételek

Ahhoz hogy megértsük hogy tudunk a python-nal együtt működni, és a beépített ellenőrzéseket a hasznunkra fordítani, meg kell értenünk a kivétel (exception) fogalmát. Amikor a python beépített könyvtárainak függvényei hibát találnak, akkor "emelnek egy kivételt" (raise an exception). A kivétel maga egy python objektum, ami tartalmazza valamilyen formátumban a "ValueError: month must be in 1..12" szerű hibaüzenetet. Amikor a kivétel fel van emelve, akkor a python alapértelmezésben kilép minden éppen futó függvényből, és kiírja a kivételben tárolt üzenetet, és minden függvényt amiből menet közben kilépett.

Azonban meg lehet állítani a kivétel emelkedését, a try-except parancs párral. Legegyszerűbb módon így:

import datetime
 
try:
    ev = int(raw_input("Szuletesunk eve? "))
    honap = int(raw_input("Honapja? "))
    nap = int(raw_input("Napja? "))
 
    szulinap = datetime.date(ev, honap, nap)
 
    print szulinap
except:
    print "Hibas datum!"

Az az except azt jelenti, hogy bármilyen hiba történik a try blokkon belül, egyből odaugrok az except blokk elejére, és végrehajtom az abban levő kódot.

Ha szeretnénk a kivételben levő üzenethez is hozzáférni, akkor el kell kapnunk a kivételt, ezt így kell:

import datetime
 
try:
    ev = int(raw_input("Szuletesunk eve? "))
    honap = int(raw_input("Honapja? "))
    nap = int(raw_input("Napja? "))
 
    szulinap = datetime.date(ev, honap, nap)
 
    print szulinap
except Exception as e:
    print "Hibas datum! Hibauzenet:"
    print e

Nézzünk egy kicsit bonyolultabb esetet, hogy jobban megérthessük az except finomságait. Kezdjük ezzel a hibakezelés nélküli kóddal:

import datetime
 
def datum_beolvas():
    ev = int(raw_input("Szuletesed eve? "))
    honap = int(raw_input("Honapja? "))
    nap = int(raw_input("Napja? "))
    return datetime.date(ev, honap, nap)
 
def nev_azonosito(nev, nevek):
    i = 1
    while i <= len(nevek):
        if nevek[i] == nev:
            return i
        i += 1
 
def szulinap_atir(nevek, szulinapok):
    nev = raw_input("Neved? ")
    azonosito = nev_azonosito(nev, nevek)
    szulinap = datum_beolvas()
    szulinapok[azonosito] = szulinap
 
nevek = ["nyuszi", "roka", "farkas"]
szulinapok = [datetime.date(1, 1, 1) for i in range(3)]
 
while True:
    szulinap_atir(nevek, szulinapok)
    print nevek
    print szulinapok
    # Kepzeljuk ide hogy fajlba is kiirja

Ha az előzőekben írtaknak megfelelően beteszünk egy try-except részt a fő kódba, akkor így néz ki:

import datetime
 
def datum_beolvas():
    ev = int(raw_input("Szuletesed eve? "))
    honap = int(raw_input("Honapja? "))
    nap = int(raw_input("Napja? "))
    return datetime.date(ev, honap, nap)
 
def nev_azonosito(nev, nevek):
    i = 1
    while i <= len(nevek):
        if nevek[i] == nev:
            return i
        i += 1
 
def szulinap_atir(nevek, szulinapok):
    nev = raw_input("Neved? ")
    azonosito = nev_azonosito(nev, nevek)
    szulinap = datum_beolvas()
    szulinapok[azonosito] = szulinap
 
nevek = ["nyuszi", "roka", "farkas"]
szulinapok = [datetime.date(1, 1, 1) for i in range(3)]
 
while True:
    try:
        szulinap_atir(nevek, szulinapok)
        print nevek
        print szulinapok
    except:
        print "Hibas bemenet!"
    # Kepzeljuk ide hogy fajlba is kiirja

Egyrészt figyeljük meg ezen a kódon, hogy ugyan a függvényeken belül történik a hiba, a függvényeken kívüli try-except is el tudja azt kapni. A másik dolog amit láthatunk, ha ezt kipróbálgatjuk, hogy ugyan a kódban van egy programozási hiba is (a nev_azonosito rosszul megy végig a listán), azt is elkapja a hibakezelésünk, és úgy jelzi mintha rossz bemenet lenne, ezzel összezavarva a felhasználót.

Itt használható az, hogy az except parancsnak meg lehet adni, hogy csak a kivételek bizonyos típusát kezelje, a többivel ne foglalkozzon. Ha olyan kivétel érkezik, ami nem felel meg az except leírásának, akkor az lép ki tovább a függvényekből, esetleg eljutva odáig hogy a felhasználó által is látható hibaüzenet lesz belőle, de ez is jobb mint ha rosszul kezelnénk. Ezért ebben az esetben csak a ValueError típusú hibákat akarjuk elkapni, mert azokról tudjuk hogy a felhasználó által megadott rossz adat okozza. És ha a hibaskezelésünk csak azzal foglalkozik, így már könnyebben megtaláljuk a programozási hibát is.

Végső kód kijavított hibával, ami csak a felhasználói hibákat jelzi:

import datetime
 
def datum_beolvas():
    ev = int(raw_input("Szuletesed eve? "))
    honap = int(raw_input("Honapja? "))
    nap = int(raw_input("Napja? "))
    return datetime.date(ev, honap, nap)
 
def nev_azonosito(nev, nevek):
    for i in range(len(nevek)):
        if nevek[i] == nev:
            return i
 
def szulinap_atir(nevek, szulinapok):
    nev = raw_input("Neved? ")
    azonosito = nev_azonosito(nev, nevek)
    szulinap = datum_beolvas()
    szulinapok[azonosito] = szulinap
 
nevek = ["nyuszi", "roka", "farkas"]
szulinapok = [datetime.date(1, 1, 1) for i in range(3)]
 
while True:
    try:
        szulinap_atir(nevek, szulinapok)
        print nevek
        print szulinapok
    except ValueError as e:
        print "Sikertelen nev valtoztatas! Hibauzenet:"
        print e
    # Kepzeljuk ide hogy fajlba is kiirja
Személyes eszközök