Yazılım geliştirme sürecinde, yazdığınız programlar genellikle tüm donanım ve yazılım kaynaklarının kusursuz çalışacağı ve kullanıcıların beklenen girişleri yapacağı varsayımıyla, yani en iyi duruma göre yazılmaya başlanır. Ancak profesyonel ve gerçek dünyadaki bir uygulamada işler her zaman planlandığı gibi gitmez. İnternet bağlantısı kopabilir, okumaya çalıştığınız bir dosya silinmiş olabilir, hard diskte boş yer kalmamış olabilir veya kullanıcıdan bir sayı girilmesi beklenirken yanlışlıkla bir harf girilebilir.
PYTHON HATA YÖNETİMİ EĞİTİMİ VİDEOMUZ İÇİN TIKLAYIN
İyi bir programcı, bu tür istisnai durumların her zaman yaşanabileceğini öngörmeli ve programının kendi kontrolü dışında aniden çökmesine asla izin vermemelidir. Beklenmeyen durumlarda kullanıcıya dostça ve anlaşılır mesajlar vererek programın çalışmaya devam etmesini veya güvenli bir şekilde sonlanmasını sağlayan bu yapıya Hata Yönetimi (Error Handling) adı verilir.
Python’da Hata Türleri Nelerdir?
Hatalar sadece program dışı faktörlerden veya kullanıcılardan kaynaklanmaz. Python’da karşılaştığımız hataları genel olarak üç temel kategoriye ayırabiliriz:
1. Yazım Hataları / Programcı Hataları (Syntax Errors): Doğrudan kodu yazan kişiden kaynaklanan, dikkatsizlik veya dilin kurallarının bilinmemesi sonucu oluşan hatalardır. Python’un dilbilgisi (syntax) kurallarına uyulmadığında ortaya çıkarlar. Örneğin, iki sayıyı toplamak için print(3 + 2) yazmanız gerekirken parantezleri unutup print 3 + 2 yazarsanız, Python size kodun neresinde hata olduğunu bir ok (^) işareti ile gösterir ve SyntaxError (Yazım Hatası) fırlatır. Bir başka örnek olarak, ogrenci_adi adında bir değişken tanımlayıp alt satırlarda bunu yanlışlıkla print(ogrnci_adi) şeklinde yazarsanız, Python bu değişkeni bulamayacağı için NameError verecektir. Bu tür hatalar, yerleri açıkça belirtildiği için çözülmesi en kolay olan hatalardır.
2. Mantıksal Hatalar (Bugs): Tespiti ve çözülmesi en zor olan hata türüdür. Programınız sorunsuz bir şekilde çalışır, hiçbir uyarı veya çökme yaşanmaz, ancak elde edilen matematiksel veya mantıksal sonuçlar yanlıştır. Örneğin, bir üçgenin alanını hesaplayan bir program yazdığınızı düşünün. Formül normalde (taban_kenari * yukseklik) / 2 olmalıdır. Eğer kodu yazarken yanlışlıkla bölü 2 yerine / 3 yazarsanız, program hata vermeden çalışıp size 4.0 gibi yanlış bir sonuç döndürecektir. Kod satırları arttıkça bu tarz mantık hatalarını bulmak çok zorlaşır; bu tür hatalara bug (böcek), bunları bulup temizleme işlemine ise debug (hata ayıklama) adı verilir.
3. İstisnai Durumlar ve Hatalar (Exceptions): Programın çalışması esnasında ortaya çıkan ve aslında gerçekleşmesi beklenmeyen hatalardır. Kodun yazımı tamamen doğrudur, ancak çalışma zamanında (runtime) işler ters gider. Örneğin, kullanıcıdan karesini almak üzere bir sayı istediğiniz şu koda bakalım:
sayi = int(input("Bir sayı yazınız: "))
karesi = sayi * sayi
print("Sayının karesi:", karesi)
Bu programda kullanıcı “6” girerse sorunsuz çalışır. Ancak kullanıcı klavyeden yanlışlıkla “y” harfini girerse, metinsel bir ifade olan “y”, int() fonksiyonu ile sayıya çevrilemeyeceği için Python ValueError (Değer Hatası) üretir ve program aniden çöker. İşte programın çökmesine neden olan bu duruma istisna (exception) denir ve kontrol altına alınması şarttır.
Hataları Kontrol Altına Almak: try ve except Blokları
Python programlama dilinde istisnai durumları yakalamak ve programın çökmesini engellemek için try ve except blokları kullanılır.
En temel kullanımı şu şekildedir:
try:
# Hata oluşması muhtemel olan riskli kodlar buraya yazılır
except:
# Eğer try bloğunda bir hata oluşursa program çökmez, bu bloğa atlar
# ve buradaki kurtarma işlemleri / mesajlar çalıştırılır
Yukarıdaki sayı karesi alma programımızı güvenli hale getirelim:
try:
sayi = int(input("Bir sayı yazınız: "))
karesi = sayi * sayi
print("Sayının karesi:", karesi)
except:
print("Bir hata oluştu! Lütfen sadece sayı giriniz.")
print("Program sona erdi!")
Kullanıcı “y” girdiğinde program try içindeki hatayı fark eder etmez except bloğuna geçer ve kullanıcıya “Bir hata oluştu!” mesajını verir. En önemlisi, program kırmızı hata yazılarıyla çökmek yerine, en sondaki “Program sona erdi!” yazısını basarak normal akışında kapanır.
Birden Fazla Hatayı Ayrı Ayrı Yakalamak
Gerçek uygulamalarda aynı kod bloğunun içinde farklı türde hatalar oluşabilir ve her hata için kullanıcıya farklı bir mesaj vermek isteyebiliriz. Örneğin, bir sayıyı diğerine bölen bir program yazdığınızı varsayın. Kullanıcı sayı yerine harf girerse ValueError, ikinci sayıyı (böleni) 0 girerse ZeroDivisionError (sıfıra bölme hatası) oluşur. Çünkü matematikte ve bilgisayarlarda bir sayının sıfıra bölünmesi tanımsızdır ve mümkün değildir.
try:
sayi1 = int(input("Bölünen: "))
sayi2 = int(input("Bölen: "))
sonuc = sayi1 / sayi2
print("Sonuç:", sonuc)
except ValueError:
print("Lütfen sadece rakamlardan oluşan bir sayı giriniz!")
except ZeroDivisionError:
print("Matematiksel hata: Bir sayıyı 0'a bölemezsiniz!")
Bu sayede, hatanın tam olarak ValueError mu yoksa ZeroDivisionError mu olduğunu anlayıp, programın akışını ona göre şekillendirebiliriz. Dilerseniz, birden fazla hataya aynı tepkiyi vermek için hataları parantez içinde gruplayabilirsiniz: except (ValueError, ZeroDivisionError):.
Orijinal Hata Mesajını Göstermek: as Kullanımı
except bloğunda sadece kendi yazdığınız özel mesajı değil, Python’un arka planda ürettiği teknik orijinal hata mesajını da görmek isteyebilirsiniz. Bunun için as deyimi kullanılır.
try:
sayi1 = int(input("1. sayı: "))
sayi2 = int(input("2. sayı: "))
print("Toplam:", sayi1 + sayi2)
except ValueError as hata:
print("Sayı girmediniz!")
print("Python'un orijinal hata mesajı:", hata)
Bu kodda meydana gelen hatanın tüm teknik detayları hata isimli değişkene aktarılır ve ekrana basılabilir. Bu işlem özellikle log tutarken (hataları bir dosyaya kaydederken) çok faydalıdır.
Her Durumda Çalışan Kodlar: finally Bloğu
try-except yapısının bir diğer güçlü bileşeni ise finally bloğudur. try bloğunda kodlar ister hatasız çalışsın isterse hata verip except bloğuna düşsün, her iki senaryonun da sonunda mutlaka çalışması gereken kodlar finally bloğuna yazılır. Özellikle dosya okuma/yazma (File I/O) veya veri tabanı işlemlerinde, açılan bir dosyanın veya bağlantının işlem bitiminde mutlaka kapatılması gerekir. finally bloğu, program çökse bile sistem kaynaklarının güvenle serbest bırakılmasını (close işlemi) garanti eder.
Kendi Hatalarımızı Fırlatmak: raise İfadesi
Python’un hata olarak görmediği bir durum, yazdığınız programın mantığına (iş kurallarına) aykırı olabilir. Böyle durumlarda kasıtlı olarak bir hata oluşturabiliriz; buna “hata fırlatma” denir ve raise anahtar kelimesi ile yapılır. Örneğin, kullanıcıdan 0 ile 10000 arasında bir sayı girmesini istediğinizi düşünün. Kullanıcı “-123” girerse Python açısından bu geçerli bir tamsayıdır ve sistem çökmez, ancak sizin programınızın amacına ters düşer.
try:
sayi = int(input("0-10000 arası bir sayı giriniz: "))
if sayi < 0 or sayi > 10000:
raise Exception("Sayı, 0-10000 arasında olmalıdır!")
print("Girdiğiniz sayı:", sayi)
except Exception as hata:
print("Bir kural ihlali oluştu:", hata)
Burada raise Exception satırı bizim özel koşulumuzu temsil eder. Şart sağlanmazsa doğrudan bir hata fırlatılır ve bu hata hemen alttaki except bloğunda yakalanır.
Savunmacı Programlama: assert İfadesi
Kodlarınızın belirli bir noktasında, bir değişkenin kesinlikle beklediğiniz bir değere veya koşula sahip olması gerektiğinden emin olmak isterseniz assert (iddia et / doğrula) ifadesini kullanabilirsiniz. Genel yapısı assert koşul, mesaj şeklindedir.
Eğer assert yanındaki koşul True (doğru) sonuç verirse program hiçbir şey olmamış gibi çalışmaya devam eder. Ancak koşul False (yanlış) çıkarsa, belirtilen mesajı taşıyan bir AssertionError fırlatılarak program durdurulur.
try:
cift_sayi = int(input("Lütfen çift bir sayı giriniz: "))
assert cift_sayi % 2 == 0, "Çift sayı girmediniz!"
print("Teşekkürler, girdiğiniz sayı:", cift_sayi)
except AssertionError as hata:
print("Hatalı işlem:", hata)
Bu örnekte cift_sayi % 2 == 0 matematiksel şartı sorgulanmaktadır. Eğer kullanıcı 19 gibi tek bir sayı girerse şart sağlanmaz ve assert mekanizması otomatik olarak AssertionError tipinde bir hata üreterek bizi uyarır.
Sonuç: Kullanıcılarınızın her zaman doğru veriler gireceğine veya sistem kaynaklarının her an erişilebilir olacağına güvenemezsiniz. Beklenmedik senaryoları öngörüp try, except, finally, raise ve assert blokları ile bu durumları yönetmek; çökmeyen, profesyonel, güvenilir ve modern yazılımlar geliştirmenin en temel şartıdır. Kendi geliştirme ortamınızda (IDE) basit bir hesap makinesi yaparak veya dosya okuma işlemleri gerçekleştirerek yukarıdaki hata yakalama bloklarını hemen denemeye başlayabilirsiniz!





