11. İstisna İşleme (Exception Handling)

Python, programlarınızda beklenmedik bir hatayı işlemek ve bunlarda hata ayıklama yeteneklerini eklemek için istisna işleme ve onaylama olmak üzere iki çok önemli özellik sunar. İstisna işleme standart hatalar ve yazılımcı tarafından oluşturulan hatalar olmak üzere ikiye ayrılabilir.

11.1. Standart istisnalar

Python içinde bulunan tüm hatalar Exception sınıfından türetilir. Aşağıdaki tüm hatalar ve açıklamaları bulunmaktadır.

İstisna adı Tanımı
Exception Tüm hataların temel sınıftır.
StopIteration Bir iterasyonun next() metodu bir nesneyi göstermediğinde oluşur.
SystemExit sys.exit() fonksiyonu tarafından oluşur.
StandardError StopIteration ve SystemExit dışındaki tüm yerleşik istisnalar için temel sınıftır.
ArithmeticError Sayısal hesaplamalar için ortaya çıkan tüm hatalar için temel sınıftır.
OverflowError Bir hesaplama, sayısal bir tür için maksimum sınırı aştığında oluşur.
FloatingPointError Float hesaplama başarısız olduğunda oluşur.
ZeroDivisionError Sıfıra bölme veya mod alma işleminde ortaya çıkar.
AssertionError Assert ifadesinin başarısız olması durumunda ortaya çıkar.
AttributeError Öznitelik referansı veya atamasının başarısız olması durumunda ortaya çıkar.
EOFError raw_input() veya input() fonksiyonundan girdi olmadığında ve dosyanın sonuna ulaşıldığında ortaya çıkar.
ImportError Bir import işlemi başarısız olduğunda oluşur.
KeyboardInterrupt Kullanıcı program yürütmeyi kestiğinde (genellikle Ctrl + c tuşlarına basıldığında) ortaya çıkar.
LookupError Tüm arama hataları için temel sınıftır.
IndexError Bir sıralı yapıda (list veya tüple gibi) indeks bulunmadığı zaman ortaya çıkar.
KeyError Bir dictionary’de belirli bir anahtar bulunmadığı zaman ortaya çıkar.
NameError Bir tanımlayıcı yerel veya global isim uzayında bulunmadığı zaman ortaya çıkar.
UnboundLocalError Bir fonksiyon veya metotta yerel bir değişkene erişmeye çalışırken ortaya çıkar, ancak bu değişkene değer atanmamıştır.
EnvironmentError Python çevresinin dışında ortaya çıkan tüm istisnalar için temel sınıftır.
IOError Var olmayan bir dosyayı açmaya çalışırken, yazdırma sırasında veya open() fonksiyonu gibi bir giriş / çıkış işlemi başarısız olduğunda ortaya çıkar. Bir anlamda işletim sistemi ile ilgili sorunlar olarak düşünülebilir.
SyntaxError Python sözdiziminde bir hata olduğunda oluşur.
IndentationError Girinti düzgün şekilde belirtilmediğinde ortaya çıkar.
SystemError Python yorumlayıcısı bir iç sorun bulduğunda ortaya çıkar, ancak bu hatayla karşılaşıldığında yorumlayıcı yorumlama işlemine devam eder.
SystemExit Python yorumlayıcısı sys.exit() fonksiyonunu kullanarak bırakıldığında ortaya çıkar. Kodda ele alınmazsa, yorumlayıcı program çalışmasını bırakır.
TypeError Belirtilen veri türü için geçersiz olan bir fonksiyon veya işlem denendiğinde oluşur.
ValueError Bir veri türü için yerleşik fonksiyon geçerli bir argüman türüne sahip olduğunda ortaya çıkar, ancak argümanların belirtilen geçersiz değerleri vardır.
RuntimeError Oluşturulan bir hata herhangi bir kategoriye girmediğinde oluşur.
NotImplementedError Kalıtımlı bir sınıfta uygulanması gereken soyut (abstract) bir yöntem gerçekte uygulanmadığında ortaya çıkar.

11.2. Python’da onaylama

Bir onaylama, programın test edilmesini bitirdiğinizde açabileceğiniz veya kapatabileceğiniz bir mantık kontrolüdür. Bir onaylamayı oluşturmanın en kolay yolu, bunu bir ortaya çıkarma (raise)-if ifadesinde benzetmektir. Bu ifade test edilir ve sonuç yanlış ise bir istisna ortaya çıkar. Python onaylamalar için assert ifadesi ile gerçekleştirilir. Programcılar genellikle geçerli girişleri kontrol etmek için bir fonksiyon başlangıcında ve geçerli bir çıkışı kontrol etmek için bir fonksiyon çağrısından sonra onaylamaları yerleştirirler.

11.2.1. assert ifadesi

Python yorumlayıcısı, bir assert ifadesi ile karşılaştığında, Python umulan doğru olan ekteki ifadeyi değerlendirir. İfade yanlışsa, Python bir AssertionError istisnasını oluşturur. Sözdizimi:

assert İfade[, argümanlar]

Eğer onaylama başarısız olursa, Python ArgumentExpression’u AssertionError için argüman olarak kullanır. AssertionError istisnası, try-except ifadesi kullanılarak başka herhangi bir istisna gibi yakalanabilir ve işlenebilir, ancak yönetilmezse, program sonlanacak ve bir iz bırakacaktır. Basit bir örnek ile açalım. Aşağıdaki örnek, sıcaklığı Kelvin’den Fahrenhayt derecesine dönüştüren bir fonksiyondur. Sıfır derece Kelvin, en son derecede soğuk olduğu için, negatif bir sıcaklık görürse fonksiyon farklı çalışır.

11.3. İstisna (Exception) nedir?

Bir istisna, programın talimatlarının normal akışını bozan bir programın yürütülmesi sırasında meydana gelen bir olaydır. Genel olarak, bir Python betiği onunla baş edemediği bir durumla karşılaştığında, bir istisna ortaya çıkarır. Bir istisna, bir hatayı temsil eden bir Python nesnesidir. Bir Python betiğinde bir istisna oluşturduğunda, istisnayı hemen ele almalıdır, aksi takdirde program sona erer ve sonlanır.

11.3.1. Bir istisnayı yönetme

Bir istisna oluşturabileceğini düşündüğünüz kod satırı var ise şüpheli kodu “try:” bloğuna yerleştirerek programınızın sonlanmasını engelleyebilirsiniz. “try:” bloğundan sonra, bir except: ifadesi eklenmeli ve sorun ile ilgili bilgi veren bir kod satırı yazabilirsiniz. Sözdizimi:

Yukarıda bahsedilen sözdizimi ile ilgili önemli noktalar:

  • Bir try bloğunun birden fazla istisna bloğu olabilir. Çünkü bir try bloğu içinde birden farklı hata tetiklenebilir.
  • Temel bir exception kullanarak birden fazla hatayı tek exception içine alabilirsiniz.
  • Exception bloklarından sonra else ifadesi eklenebilir. Bu bölüm try bloğundan hata oluşma ise çalışır.
  • Else bloğu hata oluşma kontrolüne ihtiyaç duymayan kodlar için uygun bir bloktur.

Şimdi bir tane hata içermeyen bir örnek bir tane de içeren bir örnek yapalım. Bunun için dosyaya yazma işlemi yapacağız.

Şimdi okuma için açılmış bir dosyay yazma işlemi yapmaya çalışalım. Yazma satırında bir istisna beklenir ve bu yüzden bu blok try ifadesi içindedir. Örneğin,

11.3.2. Genel istisna

Yukarıdaki örnekte IOError istisna sınıfı kullanıldı. Aslında tüm istisnalar exception temel sınıfına bağlı olduğunu belirtmiştik. Eğer istisnanın tam türünü bilmiyorsanız sadece except ifadesini kullanıp hataları yakalayabilirsiniz. Sözdizimi:

Bu tür bir try-except ifadesi, gerçekleşen tüm özel durumları yakalar. Bu tür bir try-except deyimini kullanmak, iyi bir programlama uygulaması olarak kabul edilmez. Çünkü böyle bir durum programcının hataya hakim olmadığını gösterir. Ayrıca ortaya çıkabilecek beklenmeyen hatalar kontrol edilemez bir şekilde yakalanmış olur.

11.3.3. Tüm istisnaları tek expect bloğunda toplama

Bütün hatalar aynı except bloğunda toplanabilir. Sözdizimi:

11.3.4. try-finally

try bloğu ile birlikte finally bloğu kullanabilirsiniz. finally bloğu, try bloğunda bir istisna oluşup oluşmadığına bakmadan yürütülmesi istenen herhangi bir kodun yerleştirileceği yerdir. Sözdizimi:

finally bloğu else bloğu ile beraber kullanılmaz.

Şimdi hem finally hem de except bloğu içeren bir örnek yapalım.

try bloğunda bir istisna ortaya çıktığında, kod hemen finally bloğa geçer. Finally bloğundaki tüm ifadeler yürütüldükten sonra istisna tekrar ortaya çıkar. try-except ifadesinin bir sonraki üst katmanında bulunuyorsa istisna ifadelerinde ele alınır.

11.3.5. Bir istisnanın argümanı

Bir istisna, problem hakkında ek bilgi veren bir değer olan bir argümana sahip olabilir. Argümanın içeriği istisnaya göre değişir. Bir istisnanın argümanını aşağıdaki gibi bir istisna koşulunda bir değişken sağlayarak yakalarsınız. Sözdizimi:

Tek bir özel istisna ile başa çıkmak için kod yazarsanız, bir değişkene sahipsinizdir. Birden çok özel durumu yakalarsanız, bir değişkenin istisnanın tuplesini takip edebilirsiniz. Bu değişken, genellikle istisnanın nedenini içeren istisnanın değerini alır. Değişken, tek bir değer veya bir tuple şeklinde birden çok değer alabilir. Bu tuple genellikle hata dizesini, hata numarasını ve bir hata konumunu içerir. Örneğin,

11.3.5. İstisnaları ortaya çıkarma

raise ifadesini kullanarak çeşitli yollarla istisnalar oluşturabilirsiniz. raise ifadesi için genel sözdizimi:

raise [Exception [, args [, traceback]]]

Burada, Expection özel durum istisna türüdür. args istisna argümanı için bir değerdir. args seçimliktir; sağlanmadığı takdirde istisna argümanı yoktur. Son argüman, traceback de isteğe bağlıdır (nadiren kullanılır) ve eğer varsa, istisna için kullanılan traceback nesnesidir.

Bir istisna bir katar, bir sınıf veya bir nesne olabilir. Python çekirdeğinin var olan istisnaların çoğu sınıftır. Yeni istisnaları tanımlamak oldukça kolaydır. Örneğin,

Not: Bir istisna yakalamak için, bir “expect” ifadesi sınıf nesnesini veya basit bir katara atılan aynı özel duruma başvurmalıdır. Örneğin, yukarıdaki istisnayı yakalamak için aşağıdaki gibi bir istisna yazmalıyız.

11.3.6. Kullanıcı-tanımlı istisnalar

Python, standart yerleşik istisnaları kullanarak kendi istisnalarınızı oluşturmanıza olanak sağlar. Örneğin,

Yukarıda RuntimeError ile ilgili bir örnektir. Burada, RuntimeError’dan alt sınıflanmış bir sınıf oluşturulur. __init__ bir yapıcı ile bilgiler alınıyor. Bir yapıcıda, bir istisna yakalandığında daha spesifik bilgileri görüntülemeniz gerektiğinde kullanıcı-tanımlı istisnalar yararlı olur. Yukarıdaki hatayı oluşturmak için aşağıdaki satırlara benzer satırlara ihtiyaç vardır.

try bloğunda, kullanıcı tanımlı istisna ortaya çıkar ve istisna blokta yakalanır. Değişken e, Networkerror sınıfının bir örneğini oluşturmak için kullanılır.