Şimdiye kadar yazdığımız bütün programlar, dikkat ettiyseniz tek bir ortak varsayım üzerine kurulu. Buna göre biz, yazdığımız programın kullanıcı tarafından nasıl kullanılmasını istiyorsak, her zaman o şekilde kullanılacağını varsayıyoruz. Örneğin sayıları toplayan bir program yazdığımızda, kullanıcının her zaman sayı değerli bir veri gireceğini düşünüyoruz. Ancak bütün iyi niyetimize rağmen, yazdığımız programlarda işler her zaman beklediğimiz gibi gitmeyebilir. Örneğin, dediğimiz gibi, yazdığımız programı, kullanıcının bir sayı girmesi temeli üzerine kurgulamışsak, kullanıcının her zaman sayı değerli bir veri gireceğinden emin olamayız
Gördüğünüz gibi, burada kullanıcının gireceği sayılara göre karekök ve kare alma işlemleri yapıyoruz. Bu kodlarda gördüğümüz ** işleci yardımıyla bir sayının herhangi bir kuvvetini hesaplayabileceğimizi biliyorsunuz. Mesela 217‘nin kaç ettiğini hesaplamak için ** işlecini kullanabiliyoruz:
Bu hatalar, programlama diline ilişkin bir özelliğin yanlış kullanımından veya en basit şekilde programcının yaptığı yazım hatalarından kaynaklanır. Programcının hataları genellikle SyntaxError şeklinde ortaya çıkar. Bu hatalar çoğunlukla programcı tarafından farkedilir ve program kullanıcıya ulaşmadan önce programcı tarafından düzeltilir. Bu tür hataların tespiti diğer hatalara kıyasla kolaydır. Çünkü bu tür hatalar programınızın çalışmasını engellediği için bunları farketmemek pek mümkün değildir...
Program kusurları, başka bir deyişle bug‘lar ise çok daha karmaşıktır. Kusurlu programlar çoğu zaman herhangi bir hata vermeden çalışır. Ancak programın ürettiği çıktılar beklediğiniz gibi değildir. Örneğin yazdığınız programda bir formül hatası yapmış olabilirsiniz. Bu durumda programınız hiçbir şey yokmuş gibi çalışır, ancak formül hatalı olduğu için hesaplamaların sonuçları yanlıştır. Örneğin daha önceki derslerimizde yazdığımız şu program yukarıdaki gibi bir kusur içerir:
Gelelim üçüncü kategori olan istisnalara (exceptions)...
Kullanıcı bir sayıyı 0 ‘a bölmeye çalışabilir. Mesela ilk sayıya karşılık 23 , ikinci sayıya karşılık 0 yazabilir.
Buradaki sorun ise, bir sayının 0 ‘a bölünmeye çalışılıyor olması. Matematikte sayılar 0 ‘a bölünemez...
Böylece hata (error), kusur (bug) ve istisna (exception) arasındaki farkları şöyle bir gözden geçirmiş olduk. Yalnız burada şunu söylemekte yarar var: Bu üç kavram arasındaki fark belli belirsizdir. Yani bu kavramların çoğu yerde birbirlerinin yerine kullanıldığını da görebilirsiniz. Örneğin exception kavramı için Türkçe’de çoğu zaman ‘hata’ kelimesini kullanıyoruz. Zaten dikkat ederseniz bu bölümün başlığı da ‘İstisna Yakalama’ değil, ‘Hata Yakalama’dır. Aynı şekilde, İngilizcede de bu kavramların çoğu yerde birbirleri yerine kullanıldığını görebilirsiniz. Dolayısıyla, konuya karşı özel bir ilginiz yoksa, hata, kusur ve istisna kavramlarını birbirinden ayırmak için kendinizi zorlamanıza gerek yok. Bu üç kavram çoğu zaman birbirinin yerine kullanılıyor da olsa, aslında aralarında bazı farklar olduğunu öğrenmişseniz bu bölüm amacına ulaşmış demektir.
Konuyla ilgili temel bilgileri edindiğimize göre asıl meseleye geçebiliriz...
Yine bildiğimiz gibi, veri dönüştürme işlemi sırasında kullanıcının uygun olmayan bir veri girmesi halinde üretilecek hata bir ValueError‘dır. Dolayısıyla except bloğu içine yazacağımız hata türünün adı da ValueError olacaktır. O yüzden ValueError adlı hatayı yakalayabilmek için şu satırları yazdık:
Hatırlarsanız bir sayının 0 ‘a bölünmesinin mümkün olmadığını, böyle bir durumda programımızın hata vereceğini söylemiştik. Bu durumu teyit etmek için etkileşimli kabukta şu kodu deneyebilirsiniz:
Daha önce de söylediğimiz gibi, bu hata mesajında bizi ilgilendiren kısım ZeroDivisionError. Demek ki bir sayı 0 ‘a bölündüğünde Python ZeroDivisionError veriyormuş. O halde şöyle bir kod yazabiliriz:
Yukarıdaki kodlarda özellikle bir nokta dikkatinizi çekmiş olmalı: Dikkat ederseniz yukarıdaki kodlar aslında bir değil iki farklı hata üretme potansiyeline sahip. Eğer kullanıcı sayı değerli veri yerine harf değerli bir veri girerse ValueError, eğer bir sayıyı 0 ‘a bölmeye çalışırsa da ZeroDivisionError hatası alıyoruz. Peki aynı kodlarda iki farklı hata türünü nasıl yakalayacağız?
try... except... as...¶
Burada except falancaHata as filanca yapısını kullanarak falancaHata‘yı filanca olarak isimlendiriyor ve daha sonra bu ismi istediğimiz gibi kullanabiliyoruz. Böylece bütün hata türleri için hem kendi yazdığınız mesajı görüntüleyebiliyor, hem de özgün hata mesajını da çıktıya eklediğimiz için, kullanıcıya hata hakkında en azından bir fikir sahibi olma imkanı vermiş oluyoruz.
try... except... else...¶
try... except... finally...¶
Burada eğer kullanıcı 23 sayısını girerse, kullanıcıya bir hata mesajı gösterilip programdan çıkılacaktır. Biz bu kodlarda Exception adlı genel hata mesajını kullandık. Burada Exception yerine her istediğimizi yazamayız. Yazabileceklerimiz ancak Python’da tanımlı hata mesajları olabilir. Örneğin NameError, TypeError, ZeroDivisionError, IOError, vb...
Burada, eğer kullanıcı bir sayıyı 0 ‘a bölmeye çalışırsa, normal bir şekilde ZeroDivisionError hatası verilecek ve programdan çıkılacaktır. Ama bu hata mesajıyla birlikte kullanıcıya ‘bir sayıyı 0’a bölemezsiniz,’ uyarısını da gösterme imkanını elde edeceğiz. Yani burada except ZeroDivisionError bloğunu herhangi bir hatayı engellemek için değil, hataya ilave bilgi eklemek için kullanıyoruz. Bunu yapmamızı sağlayan şey tabii ki bu kodlar içinde görünen raise adlı deyimdir...
Gördüğünüz gibi, AttributeError adlı hatayı vereceğini bildiğimiz kısmı bir try... except bloğu içine aldık. Eğer programımız AttributeError hatasını veriyorsa, programımızın çalıştırıldığı sistem Python’ın 2.7 sürümünden daha düşük bir sürümü kullanıyor demektir. O yüzden kullanıcıya _2x_metni ‘ni gösteriyoruz.