11 - Hata Yakalama - Hatalarla Baş Etmenin Yolları
2024
Hata yönetimi
SyntaxError
NameError
TypeError
ValueError
IndexError
KeyError
ZeroDivisionError
FileNotFoundError
try-except
Bloklarıtry-except
blokları kullanılır.
try
bloğu içinde, hata oluşabilecek kodlar yer alır.except
bloğu, hata oluştuğunda yapılacak işlemleri içerir.try
bloğu içinde bir hata oluşursa, programın akışı except
bloğuna yönlendirilir.Sözdizim
Örnek:
except
bloğutry
bloğunda birden fazla hata türü oluşabilir.except
bloğu kullanabiliriz.Örnek:
except
bloğunda, as
anahtar kelimesi kullanarak yakalanan hataya bir isim verilebilir ve hata mesajına bu isimle erişilebilir.Örnek:
else
Bloğu: Hata olmadığında çalıştırılacak kodlarelse
bloğu, try
bloğu içinde hiçbir hata oluşmadığında çalıştırılacak kodları içerir.try
bloğunda hata oluşması durumunda çalıştırılmak istenmeyen kodları ayırmak için kullanılır.Örnek
Neden else
Bloğu Kullanmalıyız?
else
bloğu, hata durumunda çalıştırılmaması gereken kodları try
bloğundan ayırır ve kodun daha okunabilir olmasını sağlar.try
bloğu içinde hata oluşursa, except
bloğu çalışır ve else
bloğu atlanır. Bu, programın mantıksal akışını daha net bir şekilde ifade eder.finally
Bloğu: Her zaman çalıştırılacak kodlarfinally
bloğu, try
bloğunda hata olsa da olmasa da her zaman çalıştırılır.Neden finally
bloğu kullanmalıyız?
finally
bloğu, try
bloğunda hata olsa bile, kaynakların serbest bırakılması (dosya kapatma, bağlantı sonlandırma gibi) gibi önemli temizlik işlemlerinin yapılmasını garanti eder.finally
bloğu, programın normal akışında veya bir hata durumunda, kaynakların düzgün bir şekilde yönetilmesini sağlar.Örnek:
raise
anahtar kelimesi ile kendi hata mesajlarımızı oluşturabiliriz.Örnek:
Genel Exception
bloğu yerine belirli hata türleri için ayrı except
blokları kullanın: Bu, farklı hata türlerine farklı şekilde yanıt vermenizi sağlar.
Hataları yakalamak yerine önlemeye çalışın: Hataları önlemek, programınızın daha güvenilir olmasını sağlar. Örneğin, bir sayıyı sıfıra bölmeden önce, bölenin sıfır olmadığını kontrol edin.
Hata Günlüğü (Logging): Hataları log dosyalarına kaydederek, hata ayıklama ve sorun giderme işlemlerini kolaylaştırın. Python’un logging modülünü kullanarak, hataları farklı seviyelerde (debug, info, warning, error, critical) loglayabilirsiniz. Log dosyaları, programın davranışı hakkında değerli bilgiler sağlar ve sorunların teşhis edilmesine yardımcı olur.
Hataları Kullanıcı Dostu Hale Getirme: Teknik hata mesajlarını, kullanıcıların anlayabileceği şekilde daha kullanıcı dostu mesajlara dönüştürün. Örneğin, FileNotFoundError hatası alındığında, kullanıcıya “Belirtilen dosya bulunamadı. Lütfen dosya yolunu kontrol edin.” gibi bir mesaj gösterin.
logging
modulülogging
modülü, esnek ve güçlü bir hata günlüğü sistemi sunar.logging
modülü, hataları ve diğer olayları önem derecesine göre sınıflandırmak için beş farklı seviye sunar:
DEBUG
: Ayrıntılı bilgi, genellikle hata ayıklama için kullanılır.INFO
: Programın normal çalışması hakkında bilgi verir.WARNING
: Potansiyel bir sorun olduğunu gösterir, ancak program çalışmaya devam eder.ERROR
: Programın belirli bir işlemi gerçekleştirmesini engelleyen bir hata oluştuğunu gösterir.CRITICAL
: Programın çalışmasını durduran kritik bir hata olduğunu gösterir.logging
modülünü kullanmalogging.getLogger(__name__)
ile bir logger nesnesi oluşturun.logging.FileHandler('hata.log')
ile log mesajlarını bir dosyaya yazabilirsiniz.logging
modülünü kullanmalogging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
ile log mesajlarına zaman damgası, log seviyesi ve mesaj ekleyebilirsiniz.logger.debug()
, logger.info()
, logger.warning()
, logger.error()
ve logger.critical()
metotlarını kullanarak log mesajları yazın.Örnek
# Formatter ayarla
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
# Logger'a handler ekle
logger.addHandler(handler)
# Örnek kod
try:
sonuc = 10 / 0
except ZeroDivisionError as e:
# Hata mesajını log dosyasına yaz
logger.error('Sıfıra bölme hatası: %s', e)
2024-11-16 17:30:00,123 - ERROR - Sıfıra bölme hatası: division by zero
İyi bir log örneği
2024-11-16 18:00:00,123 - ERROR - Veri tabanı bağlantı hatası: Kullanıcı adı veya şifre yanlış (kullanici_adi: test_kullanici, veri_tabani: my_database)
Kötü bir log örneği
Hata!
İpuçları
Logları Uygun Hedeflere Yönlendirin: Okunabilirlik ve erişilebilirlik
logging
modülü, log mesajlarını farklı hedeflere yönlendirmek için handler’lar sunar. En yaygın kullanılan handler’lar:
FileHandler
: Log mesajlarını bir dosyaya yazar.StreamHandler
: Log mesajlarını konsola (standart çıktı) veya başka bir akışa yazar.SMTPHandler
: Log mesajlarını e-posta ile gönderir.Log Rotasyonu: Disk alanını verimli kullanın.
Log dosyaları zamanla büyüyebilir ve disk alanını tüketebilir.
Log rotasyonu, log dosyalarının boyutunu ve sayısını kontrol altında tutmak için kullanılan bir tekniktir.
logging modülü, log rotasyonunu destekleyen RotatingFileHandler ve TimedRotatingFileHandler gibi handler’lar sunar.
Bağlamsal Bilgi Ekleyin: Hataları Anlamayı Kolaylaştırın
Log mesajlarına, hatanın veya olayın bağlamını anlamak için gerekli bilgileri ekleyin. *Örneğin, kullanıcı kimliği, istek URL’si, işlem kimliği gibi bilgiler, hatayı daha hızlı bir şekilde teşhis etmenize yardımcı olabilir.
Problemleri try-except
bloklarını kullanarak çözün:
Problem: Kullanıcıdan bir dosya adı alınız. Bu dosyayı okuyunuz ve içindeki her satırın bir sayı olduğunu varsayarak, bu sayıları toplayınız. Dosya bulunamazsa, kullanıcıya “Dosya bulunamadı!” uyarısı veriniz. Dosya içindeki satırlar sayıya dönüştürülemezse (örneğin, harf içeren bir satır varsa), bu satırı atlayıp bir sonraki satıra geçiniz ve kullanıcıya “Geçersiz veri içeren satır(lar) atlandı.” uyarısı veriniz. Son olarak, toplamı ekrana yazdırınız.
İpucu: open()
, readlines()
, int()
, try-except
, FileNotFoundError
, ValueError
def dosya_toplami():
try:
dosya_adi = input("Dosya adını girin: ")
with open(dosya_adi, "r") as dosya:
satirlar = dosya.readlines()
toplam = 0
gecersiz_satir_sayisi = 0
for satir in satirlar:
try:
sayi = int(satir)
toplam += sayi
except ValueError:
gecersiz_satir_sayisi += 1
if gecersiz_satir_sayisi > 0:
print("Geçersiz veri içeren satır(lar) atlandı.")
print("Toplam:", toplam)
except FileNotFoundError:
print("Dosya bulunamadı!")
dosya_toplami()
Problem: Kullanıcıdan iki sayı alınız (x ve y). x’i y’ye bölünüz ve sonucu ekrana yazdırınız. Kullanıcı sayı yerine harf veya başka bir karakter girerse, “Geçersiz giriş! Lütfen sayı giriniz.” uyarısı veriniz. Y sayısı sıfır ise, “Sıfıra bölme hatası!” uyarısı veriniz.
İpucu: input()
, int()
, try-except
, ValueError
, ZeroDivisionError
Problem: Bir öğrencinin notlarını saklamak için bir sözlük kullanıyorsunuz. Sözlükte öğrencinin adı anahtar, notları ise bir liste olarak değer olarak tutuluyor. Kullanıcıdan öğrencinin adını ve yeni notunu alınız. Eğer öğrenci sözlükte yoksa, “Öğrenci bulunamadı!” uyarısı veriniz ve öğrenciyi sözlüğe ekleyip notunu giriniz. Eğer öğrencinin notları arasında 100’den büyük veya 0’dan küçük bir not varsa, “Geçersiz not! Not 0-100 aralığında olmalıdır.” uyarısı veriniz ve notu eklemeyiniz. Aksi takdirde, notu öğrencinin not listesine ekleyiniz. Son olarak, öğrencinin güncel notlarını ekrana yazdırınız.
İpucu: Sözlükler, try-except
, KeyError
, ValueError
def not_ekle():
ogrenci_notlari = {
"Ahmet": [80, 90, 75],
"Ayşe": [95, 100, 85],
}
try:
ad = input("Öğrencinin adınıgirin: ")
not_ = int(input("Notu girin:"))
if not_ < 0 or not_ > 100:
raise ValueError("Geçersiznot! Not 0-100 aralığındaolmalıdır.")
if ad in ogrenci_notlari:
ogrenci_notlari[ad].appen(not_)
else:
print("Öğrencibulunamadı!")
ogrenci_notlari[ad] =[not_]
print(f"{ad} öğrencisininnotları: {ogrenci_notlari[ad]")
except ValueError as e:
print(f"Hata: {e}")
except KeyError:
print("Öğrenci adı geçerli birstring olmalıdır.")
not_ekle()
Problem: Bir listede belirli bir indeksteki elemanı kullanıcıya göstermek istiyorsunuz. Kullanıcıdan bir indeks numarası alınız. Eğer girilen indeks numarası liste sınırları içindeyse, o indeksteki elemanı ekrana yazdırınız. Eğer indeks numarası liste sınırları dışında ise veya sayı dışında bir değer girildiyse, “Geçersiz indeks! Lütfen geçerli bir indeks numarası giriniz.” uyarısı veriniz.
İpucu: Listeler, try-except
, IndexError
, ValueError
def indeks_elemani():
my_list = ["elma", "armut","çilek", "muz"]
try:
indeks = int(input("İndeksnumarasını girin: "))
if 0 <= indeks < len(my_list):
print(f"Listedeki{indeks}. eleman: {my_lis[indeks]}")
else:
raise IndexError("Geçersizindeks!")
except IndexError:
print("Geçersiz indeks! Lütfengeçerli bir indeks numarasıgiriniz.")
except ValueError:
print("Geçersiz giriş! Lütfenbir sayı giriniz.")
indeks_elemani()