Hata Yönetimi: try ve except (Python Dersi 13)

Bu seride şimdiye kadar birçok hata gördük: ValueError, KeyError, TypeError… Her seferinde program olduğu yerde durdu ve kırmızı bir mesaj yazdı. Gerçek bir uygulamada bu kabul edilemez. Kullanıcı yanlış bir şey yazdı diye bir banka uygulamasının kapandığını düşün.

Bu derste hataları yakalamayı, onlara anlaşılır bir cevap vermeyi ve gerektiğinde kendi hatamızı oluşturmayı öğreniyoruz.

Kodların hepsi Colab’da hazır: Colab’da Aç

Hatalar programı durdurur

sayi = int("abc")
print("Bu satır hiç çalışmaz.")
# ValueError: invalid literal for int() with base 10: 'abc'

Python’da bu tür hatalara istisna (exception) deniyor. Bir istisna oluştuğunda Python o anda yaptığı işi bırakıyor. Biz bir şey söylemedikçe de programı tamamen durduruyor.

try ve except

try:
sayi = int("abc")
print("Bu satır çalışmaz.")
except ValueError:
print("Bu bir sayı değil.")
print("Program devam ediyor.")
Bu bir sayı değil.
Program devam ediyor.

Okunuşu basit: “Şunu dene. Eğer ValueError olursa, onun yerine şunu yap.” try bloğunun içinde hata çıktığı anda geri kalan satırlar atlanıyor ve doğrudan except bloğuna geçiliyor. Sonra program kaldığı yerden devam ediyor.

Farklı hatalar, farklı cevaplar

Bir try bloğunun altına birden fazla except yazabilirsin. Her hata türüne ayrı bir cevap veriyorsun:

def bol(a, b):
try:
sonuc = int(a) / int(b)
except ValueError:
return "Lütfen sayı gir."
except ZeroDivisionError:
return "Sıfıra bölünemez."
return sonuc
print(bol("10", "2")) # 5.0
print(bol("on", "2")) # Lütfen sayı gir.
print(bol("10", "0")) # Sıfıra bölünemez.

En sık karşılaşacağın hatalar:

HataNe zaman olur?Örnek
ValueErrorDeğerin türü doğru ama içeriği uygun değilint("abc")
TypeErrorİşlem bu türle yapılamıyor"5" + 3
ZeroDivisionErrorSıfıra bölme10 / 0
KeyErrorSözlükte olmayan anahtarnotlar["Zeynep"]
IndexErrorListede olmayan sıra[1, 2, 3][10]
FileNotFoundErrorAçılmak istenen dosya yokDers 14’te göreceğiz

Hata mesajını yakalamak: as

Hatanın ayrıntısını da kullanmak istersen as ile bir değişkene alabilirsin:

notlar = {"Ayşe": 85, "Mert": 45}
try:
print(notlar["Zeynep"])
except KeyError as hata:
print("Bulunamayan anahtar:", hata)
# Bulunamayan anahtar: 'Zeynep'

Kod Kartı #06’da aynı durumu get() ile çözmüştük. İkisi de doğru; get kısa bir varsayılan değer için, try ise hata durumunda daha fazla şey yapman gerektiğinde daha uygun.

else ve finally

try bloğuna iki parça daha eklenebiliyor:

def oku(metin):
try:
sayi = int(metin)
except ValueError:
print(f"{metin!r} sayıya çevrilemedi.")
else:
print(f"Başarılı: {sayi}")
finally:
print("Kontrol bitti.")
oku("42")
oku("kırk iki")
Başarılı: 42
Kontrol bitti.
'kırk iki' sayıya çevrilemedi.
Kontrol bitti.
  • else: Hiç hata olmazsa çalışır.
  • finally: Her durumda çalışır, hata olsa da olmasa da. Bir dosyayı kapatmak ya da bir bağlantıyı sonlandırmak gibi “ne olursa olsun yapılmalı” işler için kullanılır.

{metin!r} ifadesi metni tırnaklarıyla yazdırıyor; boşluklu ya da boş bir girişi fark etmeyi kolaylaştırıyor.

Kendi hatanı fırlatmak: raise

Bazen Python için her şey doğru görünür ama senin programın için değildir. Mesela eksi bir yaş. Böyle durumlarda hatayı kendin oluşturabilirsin:

def yas_kaydet(yas):
if yas < 0:
raise ValueError("Yaş negatif olamaz.")
return f"Yaş kaydedildi: {yas}"
try:
yas_kaydet(-3)
except ValueError as hata:
print("Hata:", hata)
# Hata: Yaş negatif olamaz.

raise ile fırlatılan bir hata, Python’un kendi hataları gibi davranıyor: Yakalanmazsa programı durduruyor, yakalanırsa except bloğuna gidiyor.

Kötü bir alışkanlık: her hatayı susturmak

except yanına hata türü yazmazsan her hatayı yakalar. İlk bakışta pratik görünüyor ama tehlikeli:

# Bunu yapma
def ortalama_kotu(notlar):
try:
return sum(notlar) / len(notlar)
except:
return 0
print(ortalama_kotu([])) # 0
print(ortalama_kotu("doksan")) # 0

Boş liste için 0 dönmesi belki kabul edilebilir. Ama ikinci satırda yanlış türde bir veri gönderdik ve fonksiyon bunu sessizce 0’a çevirdi. Gerçek bir programda bu tür hataları bulmak günler sürebilir. Kural: Sadece beklediğin ve ne yapacağını bildiğin hatayı yakala.

# Bunu yap
def ortalama(notlar):
try:
return sum(notlar) / len(notlar)
except ZeroDivisionError:
return None

Bu sürüm boş listeyi yakalıyor, yanlış türde veri gelirse ise hatayı görmeni sağlıyor.

Mini program: güvenli not girişi

Ders 10’daki sayı tahmin oyununda kullanıcı girişini isdigit() ile kontrol etmiştik. Bu yöntem eksi sayıları ve ondalıklı sayıları da “rakam değil” diye reddediyordu. try ile daha sağlam bir sürüm yazalım:

def not_iste(mesaj):
"""0 ile 100 arasında bir not alana kadar sorar."""
while True:
cevap = input(mesaj)
try:
puan = float(cevap.replace(",", "."))
except ValueError:
print("Lütfen bir sayı yaz.")
continue
if 0 <= puan <= 100:
return puan
print("Not 0 ile 100 arasında olmalı.")
notlar = [not_iste(f"{i}. not: ") for i in range(1, 4)]
print("Ortalama:", round(sum(notlar) / len(notlar), 1))
1. not: doksan
Lütfen bir sayı yaz.
1. not: -5
Not 0 ile 100 arasında olmalı.
1. not: 85
2. not: 70,5
3. not: 101
Not 0 ile 100 arasında olmalı.
3. not: 90
Ortalama: 81.8

replace(",", ".") satırına dikkat: Türkiye’de ondalık sayıları virgülle yazıyoruz, Python ise nokta bekliyor. Kullanıcı “70,5” yazdığında virgülü noktaya çevirip öyle deniyoruz. Ders 11’deki Türkçe I/İ tuzağı gibi, bu da Türkçe kullanıcılar için yazılan programların küçük ama önemli bir detayı.

Son satırdaki liste üreteci de Ders 12’den: not_iste fonksiyonunu üç kez çağırıp sonuçları bir listeye topluyor.

Alıştırmalar

  1. Kullanıcıdan iki sayı alıp birinciyi ikinciye bölen bir program yaz. Sayı olmayan girişte ve sıfıra bölmede anlaşılır bir mesaj ver.
  2. ["10", "yirmi", "30", "", "40"] listesindeki metinleri tam sayıya çevir; çevrilemeyenleri atla ve kaç tanesinin atlandığını yazdır.
  3. Bir sözlükte anahtarı arayan bul(sozluk, anahtar) fonksiyonunu get kullanmadan, try ve except KeyError ile yaz.
  4. sifre_kontrol(sifre) fonksiyonu yaz: Şifre 8 karakterden kısaysa ValueError fırlatsın. Fonksiyonu bir kısa bir uzun şifreyle dene.

Cevaplar Colab not defterinin sonunda.

Bu derste ne öğrendik?

  • Bir istisna oluştuğunda Python programı durdurur; try ve except ile bunu yakalarız.
  • Farklı hata türleri için ayrı except blokları yazılabilir; as ile hata mesajına ulaşılır.
  • else hata olmazsa, finally her durumda çalışır.
  • raise ile kendi hatamızı fırlatabiliriz.
  • Sadece beklediğin hatayı yakala; türsüz except hataları saklar.

Sıradaki ders

Python Dersi 14’te dosya okumayı ve yazmayı öğreniyoruz. Bu derste öğrendiğin try ve except, olmayan bir dosyayı açmaya çalıştığında hemen işine yarayacak.

Devamını oku


Hatice Özbolat | Teknoloji ve AI Rehberi sitesinden daha fazla şey keşfedin

Son gönderilerin e-postanıza gönderilmesi için abone olun.

Comments

Bir yanıt yazın