- Python'da hata ve istisna ne demektir?
- try-except yapısının temeli
- Birden fazla hata, else ve finally
- raise: kendi hatanızı fırlatmak ve yeniden fırlatmak
- Özel istisna sınıfı yazmak
- Örnek senaryo: dış kaynaktan veri okuyan bir betik
- Sık yapılan hatalar
- Mindset programlarında bu beceriyi nerede çalışırsınız?
- Sık sorulan sorular
Python'da hata yönetimi: try-except ve kendi istisnalarınız
Python'da try, except, else, finally yapısı, raise ile hata fırlatma ve özel istisna sınıfı yazma yöntemini örneklerle ve sık yapılan hatalarla öğrenin.
Python'da hata ve istisna ne demektir?
Bir Python programı farklı nedenlerle durabilir: yazım hatası yüzünden hiç başlamadan ya da çalışırken beklenmedik bir durumla karşılaşıp. Çalışma sırasında ortaya çıkan bu türe istisna (exception) denir. Sıfıra bölme, olmayan bir dosyayı açma, listede olmayan bir indekse erişme, sayıya çevrilemeyen bir metni sayıya çevirmeye çalışma bunlara örnektir.
İstisna yakalanmazsa Python programı durdurur ve hatanın hangi satırda, hangi çağrı zinciriyle oluştuğunu gösteren bir izleme (traceback) yazdırır. Hata yönetiminin amacı bu durdurmayı yok saymak değil, beklenen sorunları kontrollü biçimde ele almaktır: kullanıcıya anlamlı bir mesaj vermek, işlemi yeniden denemek, ara sonucu kaydedip temiz biçimde kapanmak ya da hatayı bir üst katmana anlamlı bir türle iletmek.
try-except yapısının temeli
Temel kalıp şöyledir: riskli kodu try bloğuna koyarsınız, hata oluşursa çalışacak kodu except bloğuna yazarsınız. Örneğin kullanıcıdan alınan bir metni sayıya çevirirken şu desen kullanılır:
- try bloğunda sayiya_cevir = int(girdi) çağrısı yapılır
- except ValueError bloğunda kullanıcıya geçerli bir sayı girmesi gerektiği söylenir
Burada kritik nokta, except satırında hangi hatayı beklediğinizi açıkça yazmanızdır. Hata sınıfı belirtilmezse (çıplak except) programı durdurmak isteyen klavye kesmesi gibi sistem sinyalleri de dahil her şey yutulur ve gerçek bir programlama hatası fark edilmeden kaybolur. Python'da istisnalar bir sınıf hiyerarşisi oluşturur; yakaladığınız sınıf, o sınıftan türeyen tüm alt sınıfları da kapsar. Genel bir Exception yakalamak son çare olmalı, mümkün olduğunca belirli sınıf tercih edilmelidir.
Hatanın kendisine erişmek için as ifadesi kullanılır: except ValueError as hata yazarsanız hata nesnesinin mesajını loglayabilir ya da kullanıcıya gösterebilirsiniz.
Birden fazla hata, else ve finally
Aynı try bloğunda farklı hatalar farklı işlem gerektirebilir. Bunun için birden fazla except bloğu yazılır; Python bunları yukarıdan aşağıya tarar ve ilk eşleşeni çalıştırır. Bu yüzden özel sınıflar önce, genel sınıflar sona yazılmalıdır. Aynı davranışı paylaşan hatalar tek except satırında bir demet halinde de yakalanabilir: except (FileNotFoundError, PermissionError).
Yapıya isteğe bağlı parçalar eklenebilir. else bloğu, try bloğunda hiç istisna oluşmadığında çalışır; yalnızca başarılı yolda yapılacak işleri buraya koymak, hangi satırın hatayı yakaladığınızı netleştirir. finally bloğu ise hata olsa da olmasa da, hatta return olsa bile çalışır; dosya kapatma, bağlantı bırakma, kilit serbest bırakma gibi temizlik işleri için uygundur.
Bu temizlik işlerinin çoğunu bugün with ifadesi (bağlam yöneticisi) üstlenir. Dosyayı with open(...) ile açtığınızda hata olsa bile kapanış güvence altına alınır; elle finally yazmanız gereken durumlar bu nedenle azalmıştır.
raise: kendi hatanızı fırlatmak ve yeniden fırlatmak
Her istisna Python'dan gelmek zorunda değildir. Bir fonksiyon geçersiz girdi alırsa raise ValueError("Miktar negatif olamaz") yazarak kendi hatanızı fırlatabilirsiniz. Böylece sorun, yanlış sonuç üretilmeden önce, kaynağına en yakın noktada ortaya çıkar. Bu yaklaşım, sessizce yanlış değer döndürüp hatayı kilometrelerce sonra patlatmaktan çok daha kolay ayıklanır.
Bir hatayı yakalayıp, işledikten sonra yukarıya iletmek de yaygındır. Tek başına raise yazmak mevcut istisnayı olduğu gibi tekrar fırlatır. Farklı türde bir hata fırlatırken orijinalini kaybetmemek için raise YeniHata(...) from hata biçimi kullanılır; izlemede hatalar birbirine zincirli görünür ve kök neden korunur. Düşük seviyeli bir veritabanı hatasını uygulamanıza özgü anlamlı bir hataya çevirmek bu desenin tipik kullanımıdır.
Bir de assert ifadesi vardır; ancak bu geliştirme sırasındaki varsayımları denetler. Kullanıcı girdisi ya da dış sistem kaynaklı doğrulamalar için raise kullanın.
Özel istisna sınıfı yazmak
Uygulamanız büyüdükçe yerleşik hata türleri yetmez. Siparişte stok yetersizse, ödeme reddedilmişse ya da bir yapılandırma dosyası eksikse bunları ayrı ve anlaşılır adlarla ifade etmek istersiniz. Özel istisna sınıfı yazmak bunun yoludur: Exception (ya da uygun bir alt sınıfı) sınıfından türeyen basit bir sınıf tanımlarsınız.
Değerli bir kalıp, projeniz için tek bir temel hata sınıfı tanımlayıp diğerlerini ondan türetmektir. Örneğin UygulamaHatasi temel sınıf, StokYetersizHatasi ve OdemeReddedildiHatasi alt sınıf olur. Çağıran kod isterse yalnızca belirli hatayı, isterse UygulamaHatasi yakalayarak tüm uygulama kaynaklı hataları tek noktadan yönetebilir.
Sınıfa ek bilgi taşıtmak da mümkündür: __init__ metodunda ürün kodu ya da istenen miktar gibi alanlar alıp nesnede saklarsanız, hatayı yakalayan kod mesajı metin ayrıştırmadan alanlara doğrudan erişir. Sınıf adlarının sonuna Hata (İngilizce kodlamada Error) eki koymak yaygın bir adlandırma geleneğidir ve okunabilirliği artırır.
Örnek senaryo: dış kaynaktan veri okuyan bir betik
Örneğin her sabah bir CSV dosyasını okuyup sonuçları bir raporda toplayan bir otomasyon betiği düşünün. Dosya bazen eksiktir, bazen bir satırdaki tutar sayı yerine metin içerir, bazen de ağ sürücüsüne erişim kesilir.
Sağlam bir akış şöyle kurulur. Dosya açma işlemi with ile yapılır, dosya yoksa FileNotFoundError yakalanır ve betik anlaşılır bir mesajla çıkar. Satır satır okurken tutar dönüşümü kendi try bloğuna alınır; bozuk satır için ValueError yakalanıp satır numarasıyla loglanır ve atlanır, ama sayaç tutulur. Böylece tek bozuk satır tüm işi durdurmaz, bozuk satır sayısı ise raporun sonunda görünür. Beklenmeyen bir hata ise yakalanıp bağlam bilgisiyle loglandıktan sonra yeniden fırlatılır; çünkü bilmediğiniz bir sorunu yutmak en tehlikeli seçimdir.
Bu tasarımın özü, bildiğiniz hataları yerelde ele almak, bilmediğiniz hataları görünür bırakmaktır.
Sık yapılan hatalar
En yaygın hata çıplak except ya da pass ile boş bırakılmış blok yazmaktır. Hatayı susturur, program sonra anlamsız bir yerde patlar ve izleme size neyin yanlış gittiğini söylemez. En azından hata loglanmalıdır; logging modülünde exception metodu, izlemeyi de kaydeder.
Bir diğer hata try bloğunu gereksiz geniş tutmaktır. Onlarca satırı tek bir try içine almak, hangi satırın hataya yol açtığını belirsizleştirir ve beklenmeyen bir yerden gelen hatayı da yakalamanıza neden olur. Yalnızca hata riski taşıyan çağrıyı sarmalayın.
Kalan tuzaklar şunlardır: • Kontrol akışını istisnalarla yönetmek: basit if kontrolüyle çözülebilen durumlar için istisna kullanmak kodu yavaşlatır ve okunmaz hale getirir • Hata mesajına kullanıcıya gösterilmemesi gereken iç bilgileri koymak • Özel hata sınıflarına anlamsız, genel adlar vermek • finally içinde return kullanıp yakalanmamış istisnayı sessizce yok etmek
Mindset programlarında bu beceriyi nerede çalışırsınız?
Python ile Programlama Eğitimi'nin modül başlıkları arasında Hatalar ve Exceptions (İstisnalar), Fonksiyonlar, Veri Yapıları, Modüller ve Paketler ile Sınıflar ve Objeler yer alır. Hata yönetimi bu akışta, fonksiyonlar ve modüller yazılırken ihtiyaç duyulan bir beceri olarak istisna başlığında işlenir; sınıflar ve objeler modülü ise sınıf kavramını işler.
Veri, yazılım ya da otomasyon ekipleri için bu modül dizisi, ekip içinde ortak bir hata yakalama ve loglama alışkanlığı kurmak adına bir başlangıç noktasıdır.
İlgili Mindset programı
Python ile Programlama Eğitimi
Sık sorulan sorular
except Exception ile çıplak except arasındaki fark nedir?
Çıplak except, sistem çıkış sinyalleri ve klavye kesmesi dahil neredeyse her şeyi yakalar; programı durdurmak isteyen sinyalleri bile engelleyebilir. except Exception ise yalnızca olağan program hatalarını yakalar ve bu açıdan daha güvenlidir. Yine de doğrusu belirli bir hata sınıfını yazmaktır.
finally bloğu ne zaman çalışır?
finally, try bloğunda hata olsa da olmasa da, hatta blok içinde return ya da break çalışsa bile çalışır. Dosya, bağlantı ve kilit gibi kaynakları serbest bırakmak için kullanılır. Çoğu durumda with ifadesi bu temizliği kendisi üstlendiği için ayrıca finally yazmanız gerekmez.
Özel istisna sınıfı yazmak zorunlu mu?
Hayır. Küçük betiklerde yerleşik ValueError ya da KeyError gibi türler yeterlidir. Uygulama büyüyüp farklı iş kuralı hatalarını ayırt etmek gerektiğinde özel sınıf, kodu okunur kılar ve çağıran tarafa yalnızca ilgili hatayı yakalama imkânı verir.
Hatayı yakalayıp loglayınca programı durdurmalı mıyım?
Hata kurtarılabilirse devam edebilirsiniz, örneğin bozuk satırı atlayıp sonrakine geçmek gibi. Kurtarılamayacak bir durumsa ya da sonuçların güvenilirliğini bozuyorsa istisnayı yeniden fırlatmak ve işlemi sonlandırmak daha doğrudur. Karar, hatanın sonraki adımları etkileyip etkilemediğine bağlıdır.
try-except performansı yavaşlatır mı?
Hata oluşmadığı sürece try bloğunun maliyeti ihmal edilebilir düzeydedir. Asıl maliyet, istisna gerçekten fırlatıldığında ortaya çıkar. Bu yüzden sık gerçekleşen, basit bir koşulla önceden kontrol edilebilen durumlarda if kullanmak daha uygundur.