• Sonuç bulunamadı

Bu bölümde yine Python Programlama Dili ile ilgili çok önemli bir konudan söz edece˘giz. Yeni konumuz Python’da Hata Yakalama. Bu bölümde Python’da hatalarla ba¸setmeyi ö˘grenece˘giz...

Hatırlarsanız önceki bölümlerde yazdı˘gımız programlarda, örne˘gin kullanıcı bizim beklentimizin aksine bir sayı yerine harf girerse programımız hata verip çöküyordu. Gelin isterseniz buna basit bir örnek verelim:

Amacımız iki sayıyı toplayan bir program yazmak olsun:

topla1 = input("Lütfen toplama i¸slemine girecek ilk sayıyı giriniz: ") topla2 = input("Lütfen toplama i¸slemine girecek ikinci sayıyı giriniz: ") sonuç = int(topla1) + int(topla2)

print(sonuç)

Bu programı çalı¸stırdı˘gımızda, programımız kullanıcı tarafından girilen iki sayıyı toplayıp ekrana yazdıracaktır. Burada i¸slerin do˘gru gitmesi kullanıcının ekrana iki adet sayı yazmasına ba˘glıdır.

E˘ger kullanıcı sayı yerine harf girerse Python’un bize verece˘gi çıktı ¸suna benzer bir ¸sey olacak-tır:

Traceback (most recent call last):

File "deneme.py", line 5, in <module>

sonuç = int(topla1) + int(topla2)

ValueError: invalid literal for int() with base 10: ’f’

Esasında daha önceki bir bölümde örnek olarak basit bir hesap makinesi yazarken de böyle bir sorunumuzun oldu˘gunu söylemi¸stik. Orada aynı zamanda sonraki bir derste bu sorunun kesin çözümünü ö˘grenece˘gimizi de söylemi¸stik. ˙I¸ste bu tür problemlerin çözümünü ¸simdi inceleye-ce˘gimiz bölümde ö˘grenece˘giz...

8.1 try... except...

Python’da hatalarla ba¸setmek için try... except... adlı bloklardan yararlanaca˘gız. Bu blokları Türkçe olarak söylememiz gerekirse ¸söyle diyebiliriz: “dene... kabul_et...”. Buradan anlayabilece˘gimiz gibi, öncelikle Python’a bir ¸sey denetece˘giz. Bu deneme esnasında bir hata meydana gelirse, Python bu hatayı kabul edecek, yani sineye çekecek ve hiçbir ¸sey olmamı¸s gibi yoluna devam edecektir. ˙Isterseniz bu sözlerimizi bir örnekle süsleyelim.

125

Geçen bölümde ¸söyle bir örnek vermi¸stik:

topla1 = input("Lütfen toplama i¸slemine girecek ilk sayıyı giriniz: ") topla2 = input("Lütfen toplama i¸slemine girecek ikinci sayıyı giriniz: ") sonuç = int(topla1) + int(topla2)

print(sonuç)

Bu programı çalı¸stırdı˘gımızda e˘ger kullanıcı sırasıyla iki tane sayı girerse ne ala!... Programımız hiç bir sorun çıkartmadan bu sayıları toplayacaktır. Ama e˘ger kullanıcı sayı girmek yerine, mesela “a” harfine basarsa programımızın ¸söyle bir hata verece˘gini biliyoruz:

Traceback (most recent call last):

File "deneme.py", line 5, in <module>

sonuç = int(topla1) + int(topla2)

ValueError: invalid literal for int() with base 10: ’a’

Bu hata mesajı bizim için önemli bazı bilgiler içeriyor. Burada bizim dikkat etmemiz gereken, bu hatanın son satırı... Görüyoruz ki hata mesajının son satırında “ValueError” ifadesi var. ˙I¸ste hata mesajının bizim i¸simize yarayacak kısmı bu. Demek ki kullanıcı sayı yerine harf girerse Python’un verdi˘gi hata türü “ValueError” imi¸s... ¸Simdi ¸söyle bir ¸sey yazalım:

try:

topla1 = input("Lütfen toplama i¸slemine girecek ilk sayıyı giriniz: ") topla2 = input("Lütfen toplama i¸slemine girecek ikinci sayıyı giriniz: ") sonuç = int(topla1) + int(topla2)

print(sonuç)

except ValueError:

print("Yanlı¸s de˘ger!")

Artık kullanıcımız sayı dı¸sında bir de˘ger girerse, programımız hata vermek yerine daha an-lamlı bir çıktı üretecek ve kullanıcıya “Yanlı¸s de˘ger!” uyarısı gösterecektir. Burada yaptı˘gımız

¸

sey, programın bütün a¸samalarını birtry... blo˘gu içine almak.. Kullanıcının sayı dı¸sı bir veri girmesi durumunda “ValueError” ile kar¸sıla¸saca˘gımızı biliyoruz. Bu hata türünü “except Val-ueError” ¸seklinde gösterip, Python’un bu hata türünü kabul etmesini istiyoruz. Aslında burada Python’a ¸su emri vermi¸s oluyoruz:

“Kullanıcıya, birbiriyle toplanacak sayıları sor! Daha sonra bu sayıları topla ve sonucu ekrana yaz! E˘ger “try” blo˘gu içinde gerçekle¸sen i¸slemlerin herhangi bir a¸ sa-masında “ValueError” hatası olu¸sursa pat diye çökmek yerine ekrana “Yanlı¸s de˘ger!”

ifadesini yazdır!”

˙Isterseniz try.. except.. blo˘gunun i¸slevini daha net görebilmek için yukarıdaki örne˘gimizi birwhile döngüsü içine alalım. Böylece programımız tekrar tekrar çalı¸ssın:

while True:

topla1 = input("Lütfen toplama i¸slemine girecek ilk sayıyı giriniz: ") topla2 = input("Lütfen toplama i¸slemine girecek ikinci sayıyı giriniz: ") sonuç = int(topla1) + int(topla2)

print(sonuç)

Gördü˘günüz gibi, bu ¸sekilde programımız her i¸slem sonunda ba¸sa dönüp kullanıcıya tekrar sayı soruyor. Tabii e˘ger kullanıcı harf yerine ba¸ska bir veri girerse programımızın çalı¸sması sona eriyor. Bir de ¸suna bakalım:

while True:

try:

topla1 = input("Lütfen toplama i¸slemine girecek ilk sayıyı giriniz: ")

topla2 = input("Lütfen toplama i¸slemine girecek ikinci sayıyı giriniz: ") sonuç = int(topla1) + int(topla2)

print(sonuç)

except ValueError:

print("yanlı¸s de˘ger!")

Programımızı çalı¸stırdı˘gımızda, kullanıcı ne tür bir veri girerse girsin programımız çalı¸smasına devam edecektir. E˘ger kullanıcı iki adet sayı girerse bunları toplayıp sonucu ekrana yazdıracak;

ama e˘ger kullanıcı sayı yerine ba¸ska bir ¸sey girerse de önce kullanıcıyı yanlı¸s de˘ger girdi˘gi konusunda uyaracak ve yine çalı¸smasına devam edecektir.

Bu demek oluyor ki,try... except... blo˘gu sayesinde programımız “ValueError” hatasıyla kar¸sıla¸ssa bile çökmeden çalı¸smaya devam edebilecektir.

Buradan, Python’da hata yakalama konusunun önemli bir faydasını ö˘grenmi¸s oluyoruz:

Bildi˘giniz gibi, Python’u kendi haline bıraktı˘gınızda, kullanıcı için pek bir ¸sey ifade etmeye-cek hata mesajları üretiyor. Bu mesajlar bir Python programcısı için çok ¸sey ifade ediyor olsa da, programımızı kullanan kimselerin bu “kriptik” hata mesajlarını anlamasını bekleyemeyiz. O yüzden onlara bu tür bulanık hata mesajları yerine, yukarıda gördü˘gümüztry... except...

bloklarını kullanarak daha anlamlı mesajlar gösterebiliriz... Ne de olsa “yanlı¸s de˘ger!” gibi bir ileti, “ValueError: invalid literal for int() with base 10: ‘a’” gibi, oldukça bilgisayarvari bir hata mesajına göre çok daha anlamlı olacaktır son kullanıcı için.

˙Isterseniz daha önce yaptı˘gımız “basit hesap makinesi”ne geri dönüp, yukarıda ö˘grendi˘gimiz yeni bilgiyi o kodlara uygulayalım. Zira hesap makinemiz de, e˘ger kullanıcı sayı yerine harf girerse çöküyordu:

Programdan çıkmak için "ç" harfine basınız...

"""

print(giri¸s)

soru = input("Yapmak istedi˘giniz i¸slemin numarasını girin: ") try:

if soru == "1":

sayı1 = int(input("Toplama i¸slemi için ilk sayıyı girin: ")) sayı2 = int(input("Toplama i¸slemi için ikinci sayıyı girin: ")) print(sayı1, "+", sayı2, "=", sayı1 + sayı2)

elif soru == "2":

sayı3 = int(input("Çıkarma i¸slemi için ilk sayıyı girin: ")) sayı4 = int(input("Çıkarma i¸slemi için ikinci sayıyı girin: ")) print(sayı3, "-", sayı4, "=", sayı3 - sayı4)

elif soru == "3":

sayı5 = int(input("Çarpma i¸slemi için ilk sayıyı girin: ")) sayı6 = int(input("Çarpma i¸slemi için ikinci sayıyı girin: ")) print(sayı5, "x", sayı6, "=", sayı5 * sayı6)

elif soru == "4":

sayı7 = int(input("Bölme i¸slemi için ilk sayıyı girin: ")) sayı8 = int(input("Bölme i¸slemi için ikinci sayıyı girin: ")) print(sayı7, "/", sayı8, "=", sayı7 / sayı8)

elif soru == "5":

sayı9 = int(input("Karesini hesaplamak istedi˘giniz sayıyı giriniz: ")) print(sayı9, "sayısının karesi =", sayı9 ** 2)

elif soru == "ç":

print("Tekrar görü¸smek üzere!") a = 0

else:

print("Yanlı¸s giri¸s.")

print("A¸sa˘gıdaki seçeneklerden birini giriniz:")

except ValueError:

print("Sadece sayı giriniz!")

Gördü˘günüz gibi, burada da yaptı˘gımız ¸sey, kullanıcının sayı yerine harf girmesi durumunda Python’un “ValueError” hatası verece˘gini bildi˘gimiz kodları try... blo˘gu içine almaktan ibaret... “ValueError” hatası alındı˘gında kullanıcıya gösterilecek mesajı ise “except ValueEr-ror” blo˘gu içinde gösteriyoruz.

Yukarıda gördü˘gümüz try... except... blokları konusunda önemli bir nokta vardır dikkat etmemiz gereken... “except ValueError” ¸seklinde bir ifade kullandı˘gımızda, Python yalnızca

“ValueError” hatalarını yakalayacaktır. Bir program “ValueError” dı¸sında da pek çok hata vere-bilir. Mesela yukarıda tekrar verdi˘gimiz hesap makinemizin bir sorunu daha var. Bu programda bölme i¸slemi sırasında bir sayıyı 0’a bölmeye çalı¸sırsak programımız ¸söyle bir hata verecektir:

Traceback (most recent call last):

File "deneme.py", line 38, in <module>

print(sayı7, "/", sayı8, "=", sayı7 / sayı8) ZeroDivisionError: int division or modulo by zero

Programlama dillerinde bir sayının sıfıra bölünmesi programın çökmesiyle sonuçlanır. O yüzden biz de yazdı˘gımız programlarda yapılan i¸slemlerin bir a¸samasında herhangi bir sayının sıfıra bölünmedi˘ginden emin olmalıyız...

Yukarıdaki hata mesajında bizi ilgilendiren kısım “ZeroDivisionError”. Dolayısıyla hata mesajını yakalarken bu ifadeyi kullanaca˘gız. Yazaca˘gımız kodun tasla˘gı ¸söyle olacak:

try:

...hata verece˘gini bildi˘gimiz kodlar...

except ZeroDivisionError:

...hata geldi˘ginde kullanıcıya gösterilecek mesaj veya yapılacak i¸slem...

Bu kodları, yukarıda “ValueError” için yazdı˘gımız kodların yerine koyabiliriz. Bu basit bir i¸s.

Peki ya aynı program içinde hem “ValueError” hatasını, hem de “ZeroDivisionError” hatasını yakalamak istersek ne yapaca˘gız? Bu daha da basit bir i¸s. Tasla˘gımız ¸söyle:

try:

...hata verece˘gini bildi˘gimiz kodlar...

except ValueError:

...ValueError hatası aldı˘gımızda yapaca˘gımız i¸slem...

except ZeroDivisionError:

...ZeroDivisionError hatası aldı˘gımızda yapaca˘gımız i¸slem...

Gördü˘günüz gibi, birden fazla hatayı aynı anda yakalamak istedi˘gimizde, her bir hata için ayrı birexcept... blo˘gu yazmamız yeterli oluyor. Elbette, yukarıdaki taslak, her bir hata mesajı için ayrı bir i¸slem yapmak istedi˘gimizde geçerli. E˘ger hangi hatayla kar¸sıla¸sılırsa kar¸sıla¸sılsın aynı mesaj gösterilecekse veya aynı i¸slem yapılacaksa kodlarımızı ¸söyle de yazabiliriz:

try:

...hata verece˘gini bildi˘gimiz kodlar...

except (ValueError, ZeroDivisionError):

...hata alınınca yapılacak i¸slem...

Burada hata mesajlarını bir demet içinde topladı˘gımıza özellikle dikkat edin.

Bir sonraki bölümde bu “hata yakalama” konusunu incelemeye devam edece˘giz. Ama önce-likle ö˘grenmemiz gereken ba¸ska ¸seyler var...