Python Hatalarını Anlamak başlığı, hata simgesi üzerinde büyüteç ve Python logosu içeren temsili ders kapağı

Python Hatalarını Anlamak: try-except ve Hata Ayıklama Rehberi

Python hata mesajlarını ve traceback’i okumayı, try-except ile beklenen hataları karşılamayı ve VS Code’da hata ayıklamanın temellerini örneklerle öğrenin.

PYTHON EĞİTİM SERİSİ · DERS 09 / 16

Tüm Python dersleri  ·  ← Önceki: Fonksiyonlar

Bir program yazdınız, çalıştırdınız ve ekranda kırmızı bir hata mesajı belirdi. Böyle bir durumda bütün kodu silip yeniden yazmak isteyebilirsiniz. Oysa hata mesajı, programın neden devam edemediğini anlamanız için size verilen bir başlangıç noktasıdır.

Örneğin bir çalışma oturumunun süresini soran program, kullanıcı sayı yerine bir kelime girdiğinde durabilir. Sorun yalnızca “yanlış bir şey yazılması” değildir. Program, aldığı metnin her zaman sayıya dönüştürülebileceğini varsaymıştır. Bu varsayımı fark ettiğimizde hem hatayı açıklayabilir hem de kullanıcıya daha iyi bir deneyim sunabiliriz.

Önceki derste kodlarımızı fonksiyonlara ayırdık. Şimdi bu parçalarda karşılaşabileceğimiz hataları okuyacak, bazı beklenen durumları try-except ile ele alacak ve programın hangi noktada ne yaptığını adım adım inceleyeceğiz. Ayrıca çalışma oturumlarını raporlayan küçük bir program geliştireceğiz.

Örnekleri Python 3 ile çalıştırabilirsiniz. Her kod kutusunu ayrı bir dosyada veya önceki örneğin içeriğini temizleyerek deneyin. Çıktı kutuları program kodu değildir. Bilerek hata veren örneklerde programın durması beklenir; bu örnekleri diğerlerinden ayrı çalıştırın. Python sürümüne ve kullandığınız ortama göre hata mesajının dosya yolu, satır numarası ve açıklaması değişebilir.

Hata mesajı neden yardımcıdır?

Bir program çalışmayı bıraktığında ilk amacımız mesajı kapatmak değil, olayın gerçekleştiği yeri ve nedenini anlamaktır. Python’un verdiği bilgi çoğu zaman üç soruya yanıt aramamızı sağlar: Hangi dosya çalışıyordu, hangi satırda sorun oluştu ve hangi tür hata meydana geldi?

Bu bilgiler tek başına her zaman bütün çözümü söylemez. Hatanın görüldüğü satır, yanlış verinin üretildiği yerden daha ileride olabilir. Yine de doğru satırdan başlayıp ilgili değişkenleri kontrol etmek, rastgele değişiklik yapmaktan daha güvenilir bir yöntemdir.

Bir de program hata vermeden yanlış sonuç üretebilir. Örneğin toplam süreyi hesaplarken + yerine - kullanırsanız Python geçerli bir işlem yaptığınız için durmayabilir. Bu tür mantık hatalarını bulmak için gerçek sonucu beklediğiniz sonuçla karşılaştırmanız gerekir.

Söz dizimi hatası ve çalışma zamanı hatası

Python kodun yapısını anlayamazsa çalıştırmaya başlamadan bir söz dizimi hatası verebilir. Aşağıdaki örnekte koşul satırının sonunda iki nokta eksiktir:

puan = 70
if puan >= 50
    print("Başarılı")

Bu örnek bilerek hatalıdır ve SyntaxError üretir. Düzeltmek için koşulun sonuna : ekleyin. Hata işareti her zaman eksik karakterin hemen üstünde olmayabilir; gösterilen satırla birlikte önceki satırı da incelemek faydalıdır.

Çalışma zamanı hatasında ise kodun yapısı geçerlidir ama yürütme sırasında bir işlem tamamlanamaz. Örneğin int("merhaba") ifadesi, metin tam sayıya dönüştürülemediği için ValueError oluşturur. Python’un hatalar ve istisnalar rehberi bu ayrımı ve hata mesajlarının yapısını açıklar.

Traceback nasıl okunur?

Çalışma zamanı hatası ele alınmadığında Python genellikle traceback adı verilen bir çağrı özeti gösterir. En alttaki satır hata türünü ve genellikle açıklamasını içerir. Üst satırlarda ise hangi dosya ve fonksiyonlardan geçilerek hataya ulaşıldığını görürsünüz.

def sureyi_hesapla():
    dakika = int("yirmi")
    return dakika

sureyi_hesapla()

Bu örnek bilerek ValueError üretir. Traceback içinde çağrının yapıldığı satırı ve fonksiyon içindeki int("yirmi") satırını görebilirsiniz. Son satırda da dönüştürmenin neden başarısız olduğuna ilişkin bir açıklama bulunur.

Okumaya en alttaki hata türünden başlayın, sonra yukarıdaki dosya ve satırları takip edin. Projede aynı isimli birden fazla dosya varsa görünen yol, gerçekten hangi dosyayı çalıştırdığınızı anlamanıza da yardımcı olur. Hata mesajını paylaşmanız gerekirse önce kişisel klasör yolları ve hassas veriler içerip içermediğini kontrol edin.

Sık karşılaşılan beş hata türü

Hata adlarını ezberlemekten çok, hangi işlemin hangi veriye uygulandığını görmek önemlidir. Aşağıdaki örnekler ayrı ayrı çalıştırıldığında belirtilen hataları üretir:

HataÖrnekİlk kontrol
ValueErrorint("abc")Değer, istenen biçime uygun mu?
TypeError"5" + 2İşlem yapılan değerlerin türleri uygun mu?
ZeroDivisionError10 / 0Bölen sıfır olabilir mi?
IndexError[10, 20][4]Listedeki o konum gerçekten var mı?
KeyError{"ad": "Ece"}["yas"]Sözlükte istenen anahtar bulunuyor mu?

Liste ve sözlüklerle çalışmayı listeler ve demetler ve sözlükler ve kümeler derslerinde görmüştük. Burada önce verinin içeriğini, ardından ona nasıl erişildiğini karşılaştırıyoruz. Hata sınıflarının ayrıntıları Python’un yerleşik istisnalar belgesinde bulunur.

NameError da sık karşılaşılır: Tanımlanmamış bir isim kullanıldığında ortaya çıkabilir. Değişken adının yazımını, tanımlandığı yeri ve fonksiyon içindeki kapsamını kontrol edin. Hata türü, çözüm için bir ipucudur; ilgili her durumda aynı çözümün geçerli olacağının garantisi değildir.

İlk inceleme: Değerleri ve türleri görün

Bir işlem beklediğiniz sonucu vermiyorsa, işlemden hemen önce programın elindeki değerleri yazdırabilirsiniz. Aşağıdaki kod geçerlidir ancak sonucu ilk bakışta şaşırtabilir:

birinci = "12"
ikinci = "8"
sonuc = birinci + ikinci
print(sonuc)
print(type(birinci).__name__)

Çıktı:

128
str

Burada iki değer metindir. + işleci bu metinleri birleştirir; matematiksel toplam üretmez. Değerleri tam sayı olarak kullanmak istiyorsanız dönüşümü uygun bir yerde yapmalısınız. Ancak dönüşümün kendisi de kullanıcıdan gelen metin geçersizse hata üretebilir.

Geçici kontrol çıktıları eklerken parola, doğrulama kodu veya kişisel bilgileri ekrana ya da ortak kayıtlara yazdırmayın. İşiniz bittiğinde yalnızca hata ayıklamak için eklediğiniz çıktıları kaldırın veya gerçek ihtiyaca uygun hâle getirin. print() yararlı bir başlangıç aracıdır; programın gerçek sorununu çözmenin yerine geçmez.

Satır numarası doğru, ama sorun başka yerde olabilir

Bir fonksiyonun sayı beklediğini düşünelim. Çağıran bölüm yanlışlıkla o fonksiyona metin gönderirse, hata fonksiyonun içindeki matematik işleminde ortaya çıkabilir. Ekrandaki satır gerçekten hatanın oluştuğu yerdir; fakat yanlış türde değerin programa nerede girdiğini anlamak için çağıran bölüme bakmanız gerekebilir.

Önce fonksiyona hangi değerin verildiğini bulun. Ardından bu değerin hangi satırda oluşturulduğunu ve arada değiştirilip değiştirilmediğini inceleyin. Değişkenin adının sayi olması, içeriğinin mutlaka sayısal bir tür olduğu anlamına gelmez. İsmin yanında değerin kendisini ve türünü kontrol edin.

Bu ayrım özellikle birden fazla fonksiyon arasında bilgi aktarılırken önem kazanır. Çağrı zincirindeki bir fonksiyon beklediğinizden farklı bir sonuç döndürmüş olabilir. Hata mesajındaki son satırdan başlayıp çağıran satırlara doğru ilerlemek, bu zinciri incelemenize yardımcı olur.

Hata mesajını paylaşmadan önce

Bir sorunu başkasına gösterirken hata mesajındaki dosya yollarını ve kişisel bilgileri kontrol edin. Gerçek kişi adlarını, erişim anahtarlarını veya özel verileri yardım istemek için hazırladığınız örneğe taşımayın.

Bilgileri temizlerken hatayı anlaşılmaz hâle getirmemeye de dikkat edin. Hata türünü, ilgili satırı ve hatayı yeniden oluşturmak için gereken küçük örneği koruyabilirsiniz. Gerçek bir değeri, aynı sorunu oluşturan hayalî bir değerle değiştirmek çoğu durumda daha uygun bir seçenektir.

Başka birinin önerdiği düzeltmeyi uygularken de doğrudan bütün programı değiştirmeyin. Önerinin hangi hatayı çözdüğünü ve neden işe yaraması gerektiğini anlamaya çalışın. Sonra kendi örneğinizde beklenen sonucu test edin. İnternetteki bir çözüm farklı bir Python sürümü veya farklı bir kullanım için yazılmış olabilir.

try ve except ne yapar?

Bazen hangi işlemin hata verebileceğini önceden bilir ve bu durumu programın normal akışının bir parçası olarak ele almak isteriz. try bloğuna denenecek işlemi, uygun except bloğuna ise belirli hata oluştuğunda yapılacak işi yazarız.

metin = "abc"

try:
    sayi = int(metin)
except ValueError:
    print("Geçerli bir tam sayı girilmedi.")

Çıktı:

Geçerli bir tam sayı girilmedi.

Python önce int(metin) işlemini dener. Bu işlem ValueError oluşturunca eşleşen except bloğu çalışır. Hata oluştuktan sonra try bloğunda kalan satırlara devam edilmez; uygun hata işleyicisine geçilir. except bittiğinde program, varsa yapıdan sonraki satırlarla devam edebilir.

Buradaki temel fikir hatayı gizlemek değildir. Beklenen bir problemi belirli bir yerde karşılamak ve sonraki adımı bilinçli biçimde seçmektir. try-except yazmak, bütün programın artık hatasız olduğu anlamına gelmez.

Hata yoksa ne olur?

Aynı yapıyı geçerli bir değerle deneyelim:

metin = "25"

try:
    sayi = int(metin)
    print("Sayı:", sayi)
except ValueError:
    print("Geçerli bir tam sayı girilmedi.")

print("Kontrol tamamlandı.")

Çıktı:

Sayı: 25
Kontrol tamamlandı.

Dönüştürme başarılı olduğundan except bloğu çalışmaz. Yapıdan sonraki mesaj ise yazdırılır. try içine yalnızca hata verme ihtimaliyle gerçekten ilgilendiğiniz işlemleri koymak, hangi satırın hatayı oluşturduğunu anlamayı kolaylaştırır.

Örneğin bir sayıyı dönüştürmek için bütün menüyü, raporlama işlemlerini ve başka hesaplamaları tek bir geniş try içine almak gerekli değildir. Beklenen ValueError ile programın başka bir yerindeki gerçek bir hatayı ayırmak için kapsamı küçük tutun.

Birden fazla hata türünü ayırmak

Bir işlem birden fazla nedenle tamamlanamayabilir. Kullanıcıdan alınan metin tam sayıya dönüşmeyebilir; dönüşse bile bölen sıfır olabilir. Her durum için ayrı mesaj verebiliriz:

metin = "0"

try:
    bolen = int(metin)
    sonuc = 100 / bolen
    print("Sonuç:", sonuc)
except ValueError:
    print("Bölen bir tam sayı olmalı.")
except ZeroDivisionError:
    print("Bölen sıfır olamaz.")

Çıktı:

Bölen sıfır olamaz.

metin değerini "abc" yaparsanız ilk except, "5" yaparsanız sonuç satırı çalışır. Programınızın hangi durumları ele aldığını bu üç girişle ayrı ayrı gözlemleyin. Kullanıcıya verilen mesaj, hangi girdiyi düzeltmesi gerektiğini anlatmalıdır.

Bazı durumlarda aynı işlemi iki hata türü için yapmak isteyebilirsiniz. Bu durumda except (ValueError, TypeError): gibi bir yapı kullanılabilir. Fakat farklı sorunlar farklı çözüm gerektiriyorsa ayrı bloklar daha açıklayıcıdır.

Hata ayrıntısını görmek: as kullanımı

Bir hata nesnesini as ile bir isme bağlayabiliriz. Bu, özellikle geliştirme sırasında mesajın ne söylediğini görmeye yardımcı olur:

try:
    int("on")
except ValueError as hata:
    print("Hata türü:", type(hata).__name__)
    print("Dönüşüm tamamlanamadı.")

Çıktı:

Hata türü: ValueError
Dönüşüm tamamlanamadı.

İsterseniz geliştirme sırasında print(hata) ile ayrıntıyı da görebilirsiniz. Ancak bu metnin tam ifadesini programınızın karar vermesi için sabit bir anahtar gibi kullanmayın; mesajlar Python sürümüne veya koşullara göre değişebilir. Hata türünü ve kendi kontrol ettiğiniz değerleri kullanmak daha güvenilir bir yaklaşımdır.

Son kullanıcıya teknik ayrıntıların tamamını göstermek her zaman gerekli değildir. “Dosya bulunamadı” gibi anlaşılır bir açıklama daha yararlı olabilir. Öte yandan bir geliştiricinin sorunu araştırabilmesi için uygun hata bilgisinin kaybolmaması da önemlidir. Bu derste temel ayrımı anlamakla yetineceğiz.

else: Hata oluşmadığında ayrı bir bölüm

try-except yapısına isteğe bağlı bir else ekleyebilirsiniz. try bloğu bir istisna oluşturmadan tamamlanırsa else çalışır:

metin = "30"

try:
    dakika = int(metin)
except ValueError:
    print("Sayı girilmedi.")
else:
    print("Girilen süre:", dakika)

Çıktı:

Girilen süre: 30

else, dönüştürme başarılı olduğunda yapılacak işi ayırmaya yardımcı olur. Bu blok içinde oluşan bir istisnanın, aynı yapıda önceki except tarafından yakalanacağını varsaymayın. try yapısının ayrıntıları Python dil başvurusunda açıklanır.

Her örnekte else kullanmak zorunda değilsiniz. Küçük bir işlem daha açık yazılabiliyorsa basit çözümü tercih edin. Önemli olan programın hangi durumda hangi yolu izleyeceğini anlayabilmektir.

finally ne zaman çalışır?

finally, bir try yapısından çıkarken genellikle çalıştırılacak temizleme işlemleri için kullanılır. İşlemin başarılı olması veya bir istisna oluşması, bu bloğun amacını değiştirmez:

try:
    sayi = int("hatalı")
except ValueError:
    print("Dönüşüm yapılamadı.")
finally:
    print("Deneme sona erdi.")

Çıktı:

Dönüşüm yapılamadı.
Deneme sona erdi.

finally bir istisnayı otomatik olarak çözmez. Eşleşmeyen bir hata varsa temizleme bloğundan sonra yayılmaya devam edebilir. Ayrıca bilgisayarın aniden kapanması veya işlemin zorla sonlandırılması gibi durumlarda herhangi bir Python satırının çalışmasını garanti edemeyiz.

Dosya işlemlerini ileride ayrı bir derste ele alacağız. Şimdilik finally bloğunu, bir işlemden çıkarken yapılması gereken işi diğer adımlardan ayıran bir yapı olarak tanıyın. Kısa örnekteki mesaj yalnızca çalışma sırasını görünür kılmak içindir.

Python’da try işleminin başarılı olduğunda else, eşleşen hatada except yoluna ilerlemesini ve ardından finally temizleme adımını gösteren basitleştirilmiş akış şeması
Python’da başarılı işlem ve eşleşen hata için try, else, except ve finally akışının basitleştirilmiş gösterimi.

Her hatayı aynı şekilde yakalamak neden sakıncalı?

Bir programın hiç durmaması her zaman doğru çalıştığı anlamına gelmez. Özellikle except: gibi hangi hatanın karşılandığını belirtmeyen bir kullanım, beklemediğiniz durumları da gizleyebilir. except Exception: da oldukça geniştir; hangi sorunu neden yakaladığınızı bilmeden varsayılan çözüm olarak kullanılmamalıdır.

Örneğin kullanıcıdan sayı alırken yalnızca ValueError bekliyorsanız onu yakalayın. Fonksiyondaki yanlış değişken adından doğan NameError ortaya çıkarsa bu, programcının düzeltmesi gereken başka bir soruna işaret edebilir. Her ikisine de “Sayıyı yanlış girdiniz” demek kullanıcıyı yanıltır.

Hata işleyicisinin içine yalnızca pass yazarak sorunu sessizce yok saymak da incelemeyi zorlaştırır. Elbette bir hatayı bilinçli olarak görmezden geldiğiniz özel durumlar olabilir; fakat bunun neden güvenli olduğunu açıklayabilmeniz gerekir. Başlangıç için beklenen dar hata türünü seçmek ve anlamlı bir sonraki adım belirlemek iyi bir alışkanlıktır.

Kullanıcıdan tekrar giriş istemek

Bir kullanıcı hatalı bilgi girdiğinde programı kapatmak yerine yeni bir deneme sunabilirsiniz. while döngüsü ile try-except birlikte kullanıldığında bu davranış açıkça kurulabilir:

def pozitif_sayi_oku():
    while True:
        metin = input("Pozitif tam sayı: ")
        try:
            sayi = int(metin)
        except ValueError:
            print("Lütfen tam sayı girin.")
            continue

        if sayi <= 0:
            print("Sayı sıfırdan büyük olmalı.")
            continue

        return sayi

sonuc = pozitif_sayi_oku()
print("Kabul edilen:", sonuc)

Örnek kullanım:

Pozitif tam sayı: abc
Lütfen tam sayı girin.
Pozitif tam sayı: -2
Sayı sıfırdan büyük olmalı.
Pozitif tam sayı: 15
Kabul edilen: 15

İlk durumda dönüşüm ValueError üretir. İkinci durumda -2 geçerli bir tam sayıdır; fakat koyduğumuz iş kuralına uymaz. Bu yüzden sayının pozitif olup olmadığını ayrı bir if ile kontrol ederiz. Dönüşüm başarısı ve iş kuralı doğruluğu aynı şey değildir.

Bu örnekte kullanıcı geçerli değer girene kadar döngü sürer. Programın doğal çıkış seçeneğine ihtiyacı varsa onu ayrıca tasarlamak gerekir; sonraki uygulamada kullanıcıya q seçeneği sunacağız. Ekran mesajları yalnızca örnektir, kullanıcı girişleri sizin yazdığınız değerlere göre değişir.

Hata ayıklama: Küçük ve tekrarlanabilir bir örnek kurun

Bir sorun büyük bir programda ortaya çıktığında bütün kodu aynı anda incelemek yorucu olabilir. Önce problemi mümkün olduğunca küçük bir örneğe taşıyın. Hangi girdiyle hata oluştuğunu, beklediğiniz sonucu ve gerçekte ne gördüğünüzü yazın.

Örneğin “ortalama yanlış” demek yerine “20 ve 40 dakika için 30 bekliyordum, ekranda 20 gördüm” demek araştırılabilir bir başlangıçtır. Ardından toplamı, kayıt sayısını ve bölme işlemine giren değerleri ayrı ayrı inceleyebilirsiniz. Bu adım, çözümü tahmin etmeden önce gözlem toplamayı sağlar.

Bir seferde tek bir değişiklik yapın ve aynı girdilerle tekrar deneyin. Aynı anda değişken adını, formülü ve menü akışını değiştirirseniz hangi müdahalenin sonucu etkilediğini anlamanız zorlaşır. Sorun düzeldikten sonra normal girişin yanında boş liste ve tek kayıt gibi sınır durumlarını da kontrol edin.

Bir sorun çözüldükten sonra, sorunu ortaya çıkaran küçük örneği saklamak da faydalıdır. Daha sonra aynı bölüm değiştiğinde aynı girdiyi tekrar deneyebilir ve hatanın geri dönüp dönmediğini görebilirsiniz. İleride öğreneceğiniz otomatik testler de bu düşünceyi daha düzenli bir yapıya taşır.

VS Code’da hata ayıklama

VS Code’da Python dosyanızı açın. İncelemek istediğiniz satırın sol tarafına tıklayarak bir kesme noktası ekleyin ve Python hata ayıklayıcıyı başlatın. Uygulamanın sürümüne ve kurulu eklentilere göre seçeneklerin görünümü değişebilir.

Program kesme noktasına geldiğinde durur. Bu sırada değişkenlerin o andaki değerlerini inceleyebilir, kodu satır satır çalıştırabilir ve bir fonksiyonun içine girebilirsiniz. Örneğin bir toplamın her döngü turunda nasıl değiştiğini görmek, yalnızca son çıktıya bakmaktan daha açıklayıcıdır.

Kesme noktasını hatanın oluştuğu satırdan biraz önceye koyup verinin oraya nasıl geldiğini inceleyin. Hata ayıklayıcı kodu sizin yerinize düzeltmez; programın çalışmasını gözlemlemenize yardımcı olur. Kurulum sorunu yaşıyorsanız VS Code Python’u görmüyor rehberimize bakabilirsiniz. Güncel araç ayrıntıları için VS Code’un Python hata ayıklama belgesini kullanabilirsiniz.

Küçük uygulama: Güvenli çalışma süresi raporu

Önceki dersteki çalışma oturumu fikrini bu kez hatalı girişleri ele alacak şekilde sadeleştirelim. Program kullanıcıdan oturum süresi alacak, geçerli süreleri listede saklayacak ve kullanıcı q yazdığında toplam ile ortalamayı gösterecek.

Kurallarımız açık olsun: Süre tam sayı ve 1 ile 240 dakika arasında olmalı. Boş giriş, harf içeren değer, sıfır, negatif sayı ve 240’tan büyük değer listeye eklenmemeli. Kullanıcı hiç geçerli değer girmeden çıkarsa sıfıra bölme yapılmamalı.

def sureyi_donustur(metin):
    try:
        dakika = int(metin)
    except ValueError:
        return None

    if not 1 <= dakika <= 240:
        return None
    return dakika


def raporla(sureler):
    if not sureler:
        print("Henüz geçerli oturum yok.")
        return

    toplam = sum(sureler)
    ortalama = toplam / len(sureler)
    print("Oturum sayısı:", len(sureler))
    print("Toplam süre:", toplam, "dakika")
    print(f"Ortalama süre: {ortalama:.1f} dakika")


def ana_program():
    sureler = []
    print("Çalışma süresi raporuna hoş geldiniz.")

    while True:
        metin = input("Süre (1-240 dakika, çıkış için q): ").strip()
        if metin.lower() == "q":
            break

        dakika = sureyi_donustur(metin)
        if dakika is None:
            print("1 ile 240 arasında bir tam sayı girin.")
            continue

        sureler.append(dakika)
        print("Oturum eklendi:", dakika, "dakika")

    raporla(sureler)


if __name__ == "__main__":
    ana_program()

Örnek kullanım:

Çalışma süresi raporuna hoş geldiniz.
Süre (1-240 dakika, çıkış için q): 25
Oturum eklendi: 25 dakika
Süre (1-240 dakika, çıkış için q): 40
Oturum eklendi: 40 dakika
Süre (1-240 dakika, çıkış için q): q
Oturum sayısı: 2
Toplam süre: 65 dakika
Ortalama süre: 32.5 dakika

sureyi_donustur fonksiyonu girilen metni sayıya çevirmeyi dener. Dönüşüm başarısızsa veya sayı belirlediğimiz aralıkta değilse None döndürür. Ana program bu sonucu kontrol eder; hatalı değeri listeye eklemeden yeni bir giriş ister.

raporla fonksiyonu önce listenin boş olup olmadığına bakar. Liste boşsa mesaj gösterip döner. Böylece ortalama hesabında sıfıra bölme yapılmaz. Liste doluysa sum() ile toplamı, len() ile oturum sayısını bulur ve ortalamayı hesaplarız.

if __name__ == "__main__": satırı, dosya doğrudan çalıştırıldığında ana programı başlatır. Fonksiyonları başka bir dosyadan içe aktardığınızda menünün kendiliğinden başlamasını engeller.

Bu uygulama verileri kalıcı olarak kaydetmez. Program kapandığında listedeki süreler bellekte kalmaz; dosyaya kaydetmeyi sonraki derslerde ayrıca öğreneceğiz. Ayrıca int() Python’un kabul ettiği tam sayı metinlerini kullanır; yalnızca belirli bir yazım biçimine izin vermek isterseniz bunu ayrıca tanımlayıp test etmelisiniz.

Uygulamayı farklı senaryolarla test edin

Örneği yalnızca 25 ve 40 değerleriyle çalıştırmak yeterli değildir. Önce programı açıp doğrudan q yazın: Geçerli oturum olmadığını belirten mesajı görmelisiniz. Bu senaryo boş liste kontrolünün gerçekten işe yarayıp yaramadığını gösterir.

Ardından 0, -1 ve 241 değerlerini deneyin. Bunlar sayıya dönüştürülebilir; ancak belirlediğimiz aralığın dışındadır. Sonra 1 ve 240 değerlerini kullanın. İki sınır değeri de kabul edilmeli ve toplam 241 dakika olmalıdır.

Bir başka denemede boş giriş, 12.5 ve harf içeren bir değer kullanın. int() bunları bu programdaki kurallarla kabul etmez ve anlaşılır uyarı gösterilir. Son olarak geçerli birkaç değerden sonra büyük Q girin; lower() dönüşümü sayesinde çıkış seçeneği yine çalışmalıdır.

Test ederken yalnızca programın hata vermemesine bakmayın. Geçersiz değerlerin gerçekten listeye eklenmediğini, oturum sayısının doğru olduğunu ve ortalamanın beklediğiniz hesapla eşleştiğini de kontrol edin. Güvenilir davranış, hata mesajının kaybolmasından daha geniş bir hedeftir.

Hatalı giriş ile program hatasını nasıl ayırırsınız?

Kullanıcının bir sayı alanına kelime yazması beklenebilir bir durumdur. Program bunu açıklayıcı bir mesajla karşılayabilir. Fakat programın kendi içinde var olmayan bir değişkeni kullanması, kullanıcıya “yanlış sayı girdiniz” denilerek geçiştirilmemelidir. İki durumda da program bir noktada ilerleyemez; buna rağmen sorumluluk ve doğru müdahale farklıdır.

Bu ayrımı yapmak için önce hatanın nerede oluştuğuna, sonra neden oluştuğuna bakın. Dönüştürmeye giren değer beklenmedikse değerin kaynağını araştırın. Değer doğru olduğu hâlde hesaplama satırındaki isim yanlışsa kodu düzeltin. Kullanıcının girdisini suçlamadan önce örneği kendi belirlediğiniz basit bir değerle de çalıştırın.

Örneğin süre programına 25 girdiğinizde oturumun eklenmesini, abc girdiğinizde ise yeniden giriş istenmesini bekliyoruz. Bu iki davranışı ayrı ayrı kontrol edebiliriz. Eğer 25 de reddediliyorsa yalnızca hata mesajını değiştirmek yerine dönüşüm fonksiyonunun ne döndürdüğünü incelemeliyiz.

Kodun sınırlarını önceden yazmak

Bir değerin kabul edilip edilmeyeceğine programı yazarken karar vermek, sonradan karşınıza çıkan her hata için yeni bir istisna eklemekten daha anlaşılırdır. Çalışma süresi örneğinde sınırı 1–240 dakika olarak belirledik. Bu sınır Python’un zorunluluğu değil; örnek uygulamanın seçtiği bir kuraldır.

Başka bir uygulamada yarım dakikalık değerler veya 240 dakikadan uzun oturumlar kabul edilebilir. Böyle bir ihtiyaç varsa veri türünü, karşılaştırmaları ve örnekleri birlikte değiştirmeniz gerekir. Yalnızca hata mesajındaki sayıyı değiştirmeniz programın gerçek davranışını değiştirmez.

Benzer şekilde, q girişini çıkış komutu olarak seçmemiz de tasarım kararıdır. Başka bir kelime kullanabilirsiniz; ancak yardım metniyle kodun aynı komutu tarif etmesi gerekir. Programın neyi desteklediğini kullanıcıya açıkça söylemek, pek çok görünür sorunu başlamadan önler.

Bir sınırı değiştirdiğinizde örnekleri de güncelleyin. Örneğin üst sınırı 300 yaparsanız 240 hâlâ kabul edilir ama yeni sınırın gerçekten çalıştığını görmek için 300 ve 301 değerlerini ayrıca denemelisiniz. Böylece yalnızca eski örneklerin geçmesine güvenmemiş olursunuz. Yeni kabul edilen bir değerin toplamı ve ortalamayı nasıl etkilediğini de hesaplayarak kontrol edin.

Son olarak, kullanıcıdan alınan bilgiyi doğruladıktan sonra başka bir işlemde tekrar değiştirebileceğinizi unutmayın. Bir fonksiyonun doğru sonuç verdiğini görmek, o sonucu kullanan her fonksiyonun da doğru olduğu anlamına gelmez. Küçük işlevleri ayrı ayrı sınamak ve ardından birlikte nasıl çalıştıklarını denemek birbirini tamamlar.

Sık sorulan sorular

try-except bütün hataları önler mi?

Hayır. Belirttiğiniz hata türünü, ilgili try bloğunda oluştuğunda ele alır. Programın başka bir bölümündeki sorunları veya beklemediğiniz hata türlerini kendiliğinden düzeltmez. Ayrıca mantık hatası gibi istisna üretmeyen yanlış sonuçları test ederek bulmanız gerekir.

SyntaxError için try-except kullanabilir miyim?

Normal bir dosyada Python kodun yapısını çözemiyorsa dosyanın o bölümünü çalıştırmaya başlamadan hata verebilir. Bu nedenle aynı hatalı dosyaya çevresinden try-except eklemek genellikle çözüm değildir. Önce söz dizimini düzeltin; dinamik kod çalıştırma gibi ileri konular bu dersin kapsamı dışındadır.

Hata mesajındaki satır her zaman asıl neden midir?

Hatanın ortaya çıktığı yer çoğu zaman orasıdır; ancak yanlış veri daha önce üretilmiş olabilir. Örneğin bir fonksiyona yanlış türde değer başka bir fonksiyondan gönderilmiş olabilir. Çağrı zincirini ve değişkenin önceki değerlerini inceleyin.

Program neden hatasız çalışıp yanlış sonuç veriyor?

Python, yazdığınız işlemin söz dizimi ve veri türleri açısından geçerli olduğunu görebilir; ancak sizin ne hesaplamak istediğinizi her zaman bilemez. Beklenen sonucu önceden hesaplayıp program çıktısıyla karşılaştırın. Formülü, işlem sırasını ve kullanılan değerleri adım adım kontrol edin.

Bu dersten sonra hangi noktaya geldik?

Artık bir hata mesajında hata türünü, dosyayı ve satırı aramaya başlayabilir; söz dizimi, çalışma zamanı ve mantık hataları arasındaki farkı açıklayabilirsiniz. try-except ile beklenen hataları ele almayı, else ve finally bölümlerinin amaçlarını ve geniş hata yakalamanın neden dikkat gerektirdiğini de gördük.

Çalışma süresi uygulamasında hatalı girişleri listeye eklemeden yeniden deneme istedik. Boş listeyi ayrı ele alarak sıfıra bölmeyi önledik ve sonucu farklı senaryolarla karşılaştırdık. Bunların her biri, programın yalnızca çalışmasını değil, beklediğimiz şekilde davranmasını anlamaya yöneliktir.

Bir sonraki dersimiz İlk Proje: Bilgi Yarışması olacak. Değişkenleri, koşulları, döngüleri, fonksiyonları ve hata kontrolünü bir araya getirerek daha kapsamlı bir uygulama hazırlayacağız.

PYTHON EĞİTİM SERİSİ · DERS 09 / 16

← Önceki: Fonksiyonlar

Sonraki: İlk Proje: Bilgi Yarışması (hazırlanıyor)

Tüm Python derslerini görüntüle →

PratikTekno Bülteni

Yeni rehberleri kaçırmayın

Yeni teknoloji rehberleri ve pratik çözümler e-postanıza gelsin.