2.25. Hataların ele alınması

Python’daki çoğu çalışma zamanı sorunu istisnalar olarak ortaya çıkar – bir şeyin yanlış gittiğini bildirmenin adlandırılmış, yapılandırılmış bir yolu. ValueError, TypeError, KeyError, OSError, MemoryError bunların hepsi birer örnektir; her biri bir sınıftır ve birini yükseltmek geçerli çağrıyı durdurur ve çevredeki kodda bir işleyici arar.

2.25.1. try / except

Bir kod bloğunun yükselttiği herhangi bir istisnayı yakalamak için onu try içine sarın:

try:
    n = int(input_text)
except ValueError:
    n = 0

int(...) dönüşümü başarısız olursa, hatayı daha ileriye yaymak yerine denetim except bloğuna atlar. input_text geçerli bir tamsayı dizesiyse, except bloğu atlanır.

Tek bir try, her biri farklı türde bir hata yakalayan birkaç except bloğuna sahip olabilir:

try:
    value = data[key]
except KeyError:
    value = None
except TypeError:
    value = -1

Python sırayla eşleştirir; istisna sınıfı uyan ilk blok sorunu ele alır. (Neredeyse her şeyin temel sınıfı olan) Exception yakalamak herhangi bir hatayı ele alır; bunu, alternatifin bir çökme olduğu programın en dış katmanı için saklayın.

Uyarı

Çıplak bir except: (anahtar kelimeden sonra sınıf olmadan) ayrıca KeyboardInterrupt‘u da yakalar – çalışan bir betiği kesmek için IDE’nin stop düğmesine bastığınızda gönderdiği istisna. Çıplak bir except: pass içine sarılmış bir döngü, kesintiyi yutar ve çalışmaya devam eder, böylece betiği durdurmanın güç döngüsü dışında bir yolu kalmaz.

Gerçekten geniş bir yakalamaya ihtiyaç duyduğunuzda çıplak except: yerine except Exception: tercih edin. KeyboardInterrupt, Exception‘dan değil BaseException‘dan miras alır, dolayısıyla except Exception: durdurma düğmesini çalışır halde bırakır.

2.25.1.1. İstisnayı inceleme

Bir istisnaya eklenen mesajı okumak için onu as ile adlandırın:

try:
    f = open("data.txt")
except OSError as e:
    print("could not open file:", e)

as ile bağlanan değişken yalnızca except bloğunun içinde geçerlidir.

2.25.2. else ve finally

Bir try bloğunun isteğe bağlı iki eklentisi vardır.

else yalnızca try yükseltme yapmadan tamamlandığında çalışır:

try:
    value = compute()
except ValueError:
    print("bad input")
else:
    print("got", value)

“İşe yaradığında ne yapılacağı”nı else içine koymak try bloğunu dar tutar – yalnızca başarısız olabilecek satır try içine aittir.

finally sonda ne olursa olsun çalışır – ister try başarılı olsun, ister yükseltsin ve ele alınmış olsun, ister yükseltsin ve yayılmak üzere olsun:

try:
    do_work()
finally:
    cleanup()
try / except / else / finally üzerinden olası dört yolu gösteren akış diyagramı: başarı else'e ardından finally'e gider; yakalanan bir istisna except'e ardından finally'e gider; yakalanmayan bir istisna finally'e gider ve ardından yayılır.

finally her zaman çalışır. else yalnızca istisna olmayan yolda çalışır.

Çoğu edinme/serbest bırakma deseni için, bir try / finally çifti yerine bir bağlam yöneticisi tercih edin – kaynağın kendisi kendi temizliğini yönetir.

2.25.3. Yaygın yerleşik istisnalar

Sık karşılaşacağınız istisnaların kısa bir listesi:

  • ValueError – doğru tür, yanlış değer (bytes([300]) – 300 doğru türdür, ancak 0..255 geçerli bayt aralığının dışındadır).

  • TypeError – tamamen yanlış tür (len(42)).

  • KeyError – bir dict içinde eksik anahtar.

  • IndexError – bir dizinin sonunu aşan dizin.

  • AttributeError – var olmayan bir özniteliğe erişme ("abc".foo).

  • OSError – bir dosya sistemi veya G/Ç hatası.

  • MemoryError – yığın belleği tükendi. Belleği kısıtlı bir çalışma zamanında bu, normal çalışma sırasında olabilir – yalnızca patolojik durumlarda değil.