Python'da istisna işleme, try/except/else/finally yapıları ve raise operatörü aracılığıyla gerçekleştirilir.
try, korunacak kod bloğunu tanımlar. İçeride bir istisna oluşursa, kontrol en yakın uygun except bloğuna geçer. Eğer bir istisna yoksa, varsa else bloğu çalıştırılır. finally bloğu her zaman çalışır — istisna olup olmamasına bakılmaksızın (örneğin, kaynakları serbest bırakmak için).
raise operatörü açıkça bir istisna çağırır veya mevcut olanı tekrar eder (tip belirtilmeden except bloğunda).
Örnek:
try: x = 1 / 0 except ZeroDivisionError as e: print(f"Hata: {e}") else: print("Hata yok") finally: print("Her zaman çalışır")
Çıktı:
Hata: division by zero
Her zaman çalışır
İnce noktalar:
Soru: "Hem try'da hem de finally'de farklı istisnalar raise edilir ise ne olur?"
Cevap: Finally'deki istisna, try'daki istisnayı "kaplar": dışarıya finally'de fırlatılan istisna çıkar.
def foo(): try: raise ValueError("try'da") finally: raise IndexError("finally'de") try: foo() except Exception as e: print(repr(e)) # Çıktı: IndexError('finally'de')
Hikaye
ETL sürecinde finally bloğunda kesinlikle veritabanı bağlantısı kapatılıyor, ancak finally içinde bir istisna fırlatılabileceği unutuluyordu (örneğin, bağlantı zaten kapatılmışsa). Sonuç — "gizli" istisna tamamen ana kodun istisnasını yutuyordu, bu da hata ayıklamayı zorlaştırıyordu.
Hikaye
Birden fazla except zinciri kullanılıyordu: genel except Exception özel olanların üzerinde. Sonuç olarak, tüm özel except'ler "ölü" kalıyordu — düşük seviye istisnalar ayrı ayrı yakalanmıyordu, bu da belirli hataların işlenmesini zorluyordu.
Hikaye
Web servisinde except bloğunda hatayı daha ileri taşımayı "raise" ile unutuyorlardı, hatayı kaydedip işlemin devam etmesine izin veriyorlardı. Sonuç olarak gerçek hatalar "kayboluyordu" ve program hatalı bir durumla çalışmaya devam ediyordu.