Kivételkezelés Pythonban

A mai bejegyzés egy kicsit rendhagyó lesz abból a szempontból, hogy általában nem írok olyasmiről, amiről található jó a magyar irodalomban. A Python nyelvről pedig van, és a kivételkezelésről is. Az előzőek elhangzottak korábban azon a cégen belüli Python tréningen, amit tartok, és a kollégák szerint vicces. Viccesen írni erről a témáról pedig szvsz nehéz, szóval úgy döntöttem, ezúttal kivételt teszek.


Az unalmas rész

Mi a kivétel? A kivétel egy olyan esemény, ami a program végrehajtása során megakasztja a normál végrehajtást. Lényegében egy olyan szituáció, amivel a Python kód nem tud megbirkózni, és megszakítva a futást egy “exception”-t, kivételt add vissza. A kivétel az a Python objektum, ami ezt a adott hibát jelképezi.

Ha nem kezeljük azonnal a szituációt amikor a Python fordító a kivételt dobta, a program leáll.

OK. Mit jelent ez?

A Világ amiben élünk törött. És vele együtt a mi kis Python kódunk is. Bárki aki kódot ír, muszáj látnia, hogy lehetetlen olyan kódot írni, ami mindig helyesen működik.

Mit lehet tenni?

A Python nyelvben a try … except… szintaxist használjuk a kivételek kezelésére. A try részben írjuk azt a kódot, amiről feltételeztük, hogy néha nem fog működni. Az except rész pedig részletezi mit tegyünk, ha a pesszimista forgatókönyv valósul meg, és a fordító tényleg kivételt dob. Egy egyszerű példa:


try:
    # megnyitunk egy fájlt, ez vagy létezik vagy nem
    fh = open("testfile", "rb")
except IOError:
    # a fájl nem létezik ami egy kivételt, nevezetesen IOError dob
    print("Hiba: a fájl nem létezik vagy nem olvasható!")

A nyelvben még definiálva van a finally eljárás is, ami minden esetben lefut, attól függetlenül, hogy a try rész működött vagy nem:


try:
    # megnyitunk egy fájlt, ez vagy létezik vagy nem
    fh = open("testfile", "rb")
except IOError:
    # a fájl nem létezik ami egy kivételt, nevezetesen IOError dob
    print("Hiba: a fájl nem létezik vagy nem olvasható!")
finally:
    print("Valami amit attól függetlenül teszünk, hogy a fájl létezik vagy nem")

Lehetőségünk van a különböző típusú kivételeket más-más módon kezelni:


# egy függvény
def teszt(a):
    return a

# milyen véletlenszerű akciót teszünk  a try részben
import numpy as np
what_should_i_do = np.random.randint(1,4,1)

        
try:
    if what_should_i_do == 1:
        # megnyitunk egy fájlt 
        fh = open("testfile", "rb")
    elif what_should_i_do == 2:
        # nullával való osztás
        1/0
    else:
        teszt()
except IOError as e:
    print("Hiba: a fájl nem létezik vagy nem olvasható!"")
except ZeroDivisionError as e:
    print("Hiba: nullával való osztáso")
except Exception as e:
    print("Hiba, minden egyéb kivétel: ", str(e))

Mi legyen a try részben?

Az mind szép és jó, de van itt egy alapvető kérdés: Mi kerüljön a try szakaszba? Szögezzünk le valamit: A kivételek tulajdonsága, hogy nem lehet biztosan előre megjósolni. Bizonyos esetekben számíthatunk rá, hogy valami nem fog működni, mint a fenti példában a fájl megnyitása. De ne ringassuk magunkat abban a hitben, hogy minden egyes lehetséges probléma eszünkbe fog jutni.

Ha ezt elfogadjuk akkor három út áll előttünk. Ezeket fogjuk most részletezni, de előtte létrehozunk egy osztályt, aminek segítségével szemléltetem a megközelítések közötti különbségeket.

A példa kedvért mondjuk legyen ez a Life (“Élet”) osztály, ami realizálása a your_live (“a te életed”) objektum lesz. Ezenkívül még legyen egy kivételünk, Frustration (Frusztráció), amit bizonyos esetekben ez az osztály dob:


# A saját Frusztáció kivételünk
class Frustration(Exception):
    def __init__(self, message):

        # Call the base class constructor with the parameters it needs
        super().__init__(message)

# Az Élet  osztály
class Life:
    # a komunkiáció másokkal nem az erős oldala az Élet osztálynak, mindig Frusztrációt eredményez
    def connect_to_others(self, thinks_you_are_say):
        raise Frustration("You are and idiot")
    # néha az Élet osztály futtatása során butaságokat teszünk csak úgy magunktól 
    def make_stupid_things(self):
        return 10/0    
    # néha meg jó dolgokat, ilyenkor valami boldogságot sugárzó zene a jutalom
    def make_good_things(self, msg):
        import random
        happy_music = ["https://www.youtube.com/watch?v=EKGUJXzxNqc", 
                 "https://www.youtube.com/watch?v=JebowNHkA_M", 
                 "https://www.youtube.com/watch?v=tVQtKyeWisQ",
                 "https://www.youtube.com/watch?v=D5Y11hwjMNs"]
        random.shuffle(happy_music)
        return happy_music[0]

your_life = Life()

Az egész életedet buborékfóliába csomagolod

Ez egy kényelmes megoldásnak tűnik, de a valóságban önámítás.

Kódban leírva egy néz ki:


try:        
    your_life = Life()
    
    import numpy as np
    what_should_i_do = np.random.randint(1,4,1)
    print(what_should_i_do)
    if what_should_i_do == 1:
        your_life.connect_to_others("Szép vagy!")
    elif what_should_i_do == 2:
        print( your_life.make_good_things("Hajléktalanok segítése.") )
    else:
        your_life.make_stupid_things()
    
except Frustration as e:
    try:
        raise("https://www.babelmatrix.org/works/hu/Ady_Endre-1877/Szeretn%C3%A9m%2C_ha_szeretn%C3%A9nek/en/1958-I_want_to_be_loved")
    except:
        print("https://www.youtube.com/watch?v=RFqPuscYk_Y")
except Exception as e:
    print("https://www.youtube.com/watch?v=ltVOXz4mxOo")

Mint látható bármit tehetünk mindig valami boldog zenét hallgathatunk.

A kommunikációt másokkal buborékfóliába csomagolod, de őszinte vagy magadhoz

Mint a fenti osztálydefinícióból tudjuk a kommunikáció másokkal valami hasonló:

Vesztet csata, de ezzel nem tehetünk semmit. Néha meg kell próbálnunk.

De lássuk be, az Élet nem csak ebből áll, néha mi magunk is teszünk jó vagy rossz dolgokat. A korábbi megközelítéssel ellentétben ezeket az eseteket nem védjük kivételkezeléssel. Fájdalmas lesz amikor saját hibáinkkal szembesülünk de legalább őszinték vagyunk magunkhoz.

Kódban:


your_life = Life()
    
import numpy as np
what_should_i_do = np.random.randint(1,4,1)
if what_should_i_do == 1:
    your_life.make_stupid_things()
elif what_should_i_do == 2:
    print( your_life.make_good_things("Képeslap küldése politikai foglyoknak.") )
else:
    try:
        your_life.connect_to_others("Jó embernek tartalak!")
    except:
        print("https://youtu.be/2W6zK9givao")

B*meg, nem érdekel, ha valami rossz akkor legyen rossz

Ha valami nem működik akkor hagyjuk, hogy összeomoljon. Sajnos ez a hozzáállás nem fizet jól. Lényegében arra kényszeríted a többieket, hogy próbálják megjavítani a közös Életeteket. Ezt pedig általában nem szeretik az emberek.

Kódban:


your_life = Life()

import numpy as np
what_should_i_do = np.random.randint(1,4,1)
if what_should_i_do == 1:
    your_life.make_stupid_things()
elif what_should_i_do == 2:
    print( your_life.make_good_things("Megdicséred a gyereket amikor jót tesz.") )
else:
    your_life.connect_to_others("Érdekes amit mondasz.")

Vagyis lényegében nem használunk kivételkezelést.

Összegzés

Nagyából ennyit szeretem volna írni a kivételkezelésről, remélem hasznos. Még lehetne írni arról, hogy miként hozzunk létre saját kivételeket, de fölöslegesnek tartom ezt külön részletezni, fentebb a Frustration és Life osztályok definiálásánál ez látható.

Hírdetés

Vélemény, hozzászólás?

Adatok megadása vagy bejelentkezés valamelyik ikonnal:

WordPress.com Logo

Hozzászólhat a WordPress.com felhasználói fiók használatával. Kilépés /  Módosítás )

Twitter kép

Hozzászólhat a Twitter felhasználói fiók használatával. Kilépés /  Módosítás )

Facebook kép

Hozzászólhat a Facebook felhasználói fiók használatával. Kilépés /  Módosítás )

Kapcsolódás: %s