39 Lisalugemine: erindid

Vaatame ühte lühikest ja lihtsat programmi:

Nüüd on vaja kontrollida, kas parool on õige või ei ole. Selleks saab kasutada tingimuslauset:

arv1 = float(input("Sisesta esimene arv: "))
arv2 = float(input("Sisesta teine arv: "))
print(f"Nende arvude jagatis on {arv1 / arv2}")

Mis juhtub siis, kui kasutaja sisestab ühe soovitud arvu (nt. 45) asemel kogemata midagi, millest Python ei oska arvu välja lugeda (näiteks 45t)? Proovi järele!

Ilmselt nägid, et Python väljastas ekraanile veateate, ning lõpetas programmi töö. Selle programmi puhul polnud see suur õnnetus, aga keerulisemates programmides, kus kasutaja on suure ülesandega poole peale jõudnud, on kahju kui selline viga programmi veateatega sulgeb. Seetõttu on Pythonisse loodud võimalused täitmisaegsete vigade e erindite „püüdmiseks“.

Vigade püüdimiseks tuleb kasutada try-lauset. Alustame näitest:

try:
    arv1 = float(input("Sisesta esimene arv: "))
    arv2 = float(input("Sisesta teine arv: "))
    print(f"Nende arvude jagatis on {arv1 / arv2}")
except:
    print("Hmm..., midagi läks vussi.")

Nii nagu if-else-lause, koosneb ka try-lause mitmest osast – võtmesõna try alla kirjutatakse laused, mida soovitakse normaalsel juhul täita ning võtmesõna except alla laused, mida täidetakse siis, kui try-osa lausete täitmisel tekib mingi viga (siit ka võtmesõna except – neid lauseid soovime täita vaid erandjuhtumitel).

Selle näite puhul on küsitav, kuivõrd try-lause lisamine midagi paremaks tegi – me küll peitsime kasutaja eest ära koleda mitmerealise veateate (kas see peitmine oli üldse hea?), aga vigase sisestuse korral jäi kasutaja ikkagi vastusest ilma. Koodi ümber paigutades saame me aga programmi, mis küsib kasutajalt arve niikaua, kuni lõpuks teisendamine ja jagamine õnnestub. Püüame ka kinni konkreetse veateate ValueError:

jätkub = True
while jätkub:
    try:
        arv1 = float(input("Sisesta esimene arv: "))
        arv2 = float(input("Sisesta teine arv: "))
        print(f"Nende arvude jagatis on {arv1 / arv2}")
        jätkub = False
    except ValueError:
        print("Sisestage korrektne arv.")
        print("Proovime uuesti!")

Siin me panime kogu programmi loogika tsüklisse, millest pääseb välja muutes tsükli jätkutingimuse väärtuseks False. Selle käsuni jõuab Python aga ainult siis, kui kõik try-osa laused edukalt läbitakse – niipea, kui kusagil eespool tekib mingi viga, hüpatakse kohe except-osasse, kus püütakse kinni ValueError ning peale selle täitmist jätkatakse uuesti tsükli algusest.

Kui me tahame selle tsükliprogrammi kenasti põhifunktsiooni sisse panna, siis peaksime koostama main-funktsioonia ja kutsuma selle välja programmi lõpus. Selliselt tuleb meeles pidada, et kõik read, mis lähevad main-funktsiooni sisse, peavad algama taandega:

def main():
    jätkub = True
    while jätkub:
        try:
            arv1 = float(input("Sisesta esimene arv: "))
            arv2 = float(input("Sisesta teine arv: "))
            print(f"Nende arvude jagatis on {arv1 / arv2}")
            jätkub = False
        except ValueError:
            print("Sisestage korrektne arv.")
            print("Proovime uuesti!")
if __name__ == "__main__":
    main()

Hoiatus!

Vigade kinnipüüdmine on põhjendatud ainult siis, kui sa tõesti oskad selle veasituatsiooniga midagi ette võtta. Vigu ei tohiks püüda kinni lihtsalt selleks, et vältida veateate ekraanile jõudmist – see võib tekitada situatsiooni, kus programmis on mingi probleem, aga ei programmeerija ega kasutaja ei saa sellest teada ning programm annab süüdimatult välja valed tulemused. Seepärast ongi hea harjumus püüda kinni konkreetsed veateated (nt ValueError) ja anda vastav tagasiside. Näiteks nulliga jagades võib juhtuda ka ZeroDivisionError, mille võiks eraldi kinni püüda ja anda ka vastav tagasiside.

Video

Kui soovid rohkem teada saada erijuhtude käsitlemisest, siis vaata videot:

Litsents

Icon for the Creative Commons Attribution 4.0 International License

Programmeerimine on loodud Eno Tõnisson, Tauno Palts, Merilin Säde, Kaarel Tõnisson jt poolt Creative Commons Attribution 4.0 International License litsentsi alusel, kui pole teisiti märgitud.

Jaga seda raamatut