Python kodu çalışma zamanında sorunlarla karşılaştığında, çoğu zaman bir istisna fırlatır. Ele alınmadan bırakılırsa, istisnalar programınızı çökertir. Ancak try-except bloklarıyla bunları yakalayabilir, zarifçe toparlanabilir ve uygulamanızı çalışır durumda tutabilirsiniz.
Bu eğitim istisnaların temelleri hakkında değil, bunu zaten Python'da İstisna ve Hata Yakalama rehberimizde ele aldık. Bunun yerine burada try-except uygulamada nasıl kullanılır, bloklarınızı nasıl yapılandırırsınız, yaygın hatalardan nasıl kaçınırsınız ve gerçek dünyada kodunuzu daha güvenilir kılan en iyi uygulamaları nasıl uygularsınız gibi konulara derinlemesine bakacağız.
Sonunda, try-except'in nasıl çalıştığını değil, aynı zamanda onu Pythonik şekilde nasıl kullanacağınızı; açık, sürdürülebilir ve üretime hazır hata yakalama kodu yazmayı da anlayacaksınız.
Python'da hata yakalama temelde beklenmeyenle başa çıkabilen programlar tasarlamakla ilgilidir. Hataları ele almak için birçok araç olsa da, try-except Python'un yaklaşımının bel kemiğidir.
Peki neden bu kadar önemli?
Python'un felsefesini yansıtır. Python'da yaygın tarz EAFP; İzin İstemektense Affını İstemek Daha Kolaydır. Her şeyi en başta kontrol etmek (bu dosya var mı? bu giriş geçerli mi? sunucu erişilebilir mi?) yerine işlemi denersiniz. Başarısız olursa istisnayı yakalar ve ele alırsınız. Bu da daha kısa, daha temiz koda yol açar.
Gerçek dünyada kodu çalışır tutar. Kullanıcı girdisi dağınık olacaktır, dosyalar kaybolacaktır, API'ler başarısız olacaktır ve ağlar kopacaktır. try-except ile kodunuz ilk sorunda çökmek yerine akıllıca tepki verir.
Yeni başlayanlar ve profesyoneller için yeterince esnektir. Yeni başlayan biri, girişi tamsayıya çevirirken bir ValueError yakalamak için try-except kullanabilir. Bir üretim sistemi ise hataları günlüğe kaydetmek, başarısız işlemleri yeniden denemek veya hata ayıklamayı kolaylaştıran özel istisnalar yükseltmek için kullanabilir.
İşte bu yüzden bu makale try-except üzerine odaklanıyor. Bunu ustalaşmak, yalnızca kusursuz koşullarda çalışan betikler ile sağlam, sürdürülebilir ve üretime hazır yazılımlar yazmak arasındaki farktır.
Bazen tek bir except yeterli olmaz. Farklı kod yolları farklı şekillerde başarısız olabilir ve çıplak bir except: ile her şeyi yakalamak pek yardımcı değildir; hataları gizleyebilir ve hata ayıklamayı bir baş ağrısına çevirebilir.
Diyelim ki bir şeyi tamsayıya dönüştürmeye ve sonra bölmeye çalışıyorsunuz. İşte yapmamanız gereken:
try:
result =int(user_input)/2except:print("Something went wrong.")Altyapı:
Bu, değişken adlarında yazım hataları veya gerçek sorunlara işaret eden beklenmedik istisnalar gibi muhtemelen gizlemek istemediğiniz şeyler de dâhil olmak üzere her şeyi yakalar.
Bunun yerine, belirli olun:
try:
result =int(user_input)/2except ValueError:print("That wasn't a number.")except ZeroDivisionError:print("Division by zero?")Altyapı:
Aynı şekilde ele alınması gereken birden fazla istisna türünüz varsa, bunları şu şekilde gruplayabilirsiniz:
try:
result = some_function()except(TypeError, ValueError):print("Something was wrong with the data.")Altyapı:
Böylece, aynı bloğu tekrar tekrar kopyalamadan yine de nelerin ters gidebileceğini net biçimde belirtmiş olursunuz.
Bir de except Exception var, bu çıplak bir except'ten iyidir ama hâlâ fazla geniştir. Beklediğiniz belirli hataları hedeflemek daha iyidir.
else ve finally Bloklarını Kullanma
try bloğu içindeki kod başarıyla çalışır ve hiçbir istisna yükseltilmezse, Python else bloğunu yürütür.
try:
user_id = get_user_id()except LookupError:print("User not found.")else:print("Welcome, user", user_id)Altyapı:
Bu, istisna yakalama mantığınızı mutlu yolunuzdan ayırmanıza yardımcı olur ve okumayı kolaylaştırır.
Bir de finally var. Ne olduğuyla ilgilenmez; ne olursa olsun çalışır. İstisna mı? Yine çalışır. İstisna yok mu? Yine çalışır. Program Ctrl‑C ile mi sonlandırıldı? Yine çalışır. Temizlik işleri için harikadır:
try:
f =open("data.txt")
process(f)except IOError:print("Couldn’t open file.")finally:
f.close()Altyapı:
Yalnız unutmayın, dosya hiç açılmadıysa f var olmamış olabilir, dikkatli olun. Dosyalarla çalışırken bunun yerine Python'un bağlam yöneticisini (with open(...) as f:) kullanabilirsiniz. Daha güvenlidir.
Python'da KeyError istisnasını etkili bir şekilde ele almak için istisna yakalama ve hata önleme gibi temel teknikleri öğrenmek isterseniz, Python KeyError İstisnaları ve Nasıl Düzeltilir eğitimimizi öneririm.
Python try-except En İyi Uygulamalar ve Yaygın Tuzaklar
Açık konuşalım: try‑except blokları yazmak biraz sanattır. Doğru yapıldığında programınızın çökmesini engeller. Kötü yapıldığında ise hataları o kadar derine gömer ki, uygulamanız çöküp kullanıcılar şikâyet edene kadar fark etmezsiniz.
İşte edinmeye değer bazı alışkanlıklar:
try bloklarını dar tutun. Yüzlerce satır kodu tek bir try içine sarmalayın demiyoruz. Bu yalnızca soruna neyin sebep olduğunu bilmeyi zorlaştırır. Bunun yerine, yalnızca başarısız olabilecek kodu sarmalayın:
# Goodtry:
value =int(data)except ValueError:print("Couldn’t convert.")# Badtry:# Tons of unrelated logic
value =int(data)
do_more()
something_else()except ValueError:print("Huh?")Altyapı:
Eylemi yapmadan önce koşulları kontrol etmekten kaçının; hatayı yakalamak daha kolaysa doğrudan deneyin. Python bunu şöyle adlandırır: EAFP, Easier to Ask Forgiveness than Permission. Bir dosyanın var olup olmadığını kontrol edip sonra açıyorsanız, yarış durumu yaratıyorsunuz. Bunun yerine:
Bu desen, dosyanın kontrol ile açma çağrısı arasında ortadan kaybolabileceği yaygın bir sorundan kaçınır. Sadece işi deneyin. Başarısız olursa, hatayı yakalayın.
Ayrıca, her şeyi yakalayıp hiçbir şey yapmayarak hataları susturmaktan kaçının. Bunu yapmayın:
Gerçekten ne yaptığınızı bilmiyorsanız, bu hataların saklanıp çoğalacağı yerdir. Mutlaka susturmanız gerekiyorsa, spesifik olun:
try:
something()except TimeoutError:# okay to ignore in this casepassAltyapı:
Ve hataları bir yere kaydedin. Tamamen yutmak, gelecekte neyin yanlış gittiğine dair hiçbir fikriniz olmayacağı anlamına gelir.
Yerleşik ve Özel İstisnalar
Python, pek çok yerleşik istisna ile birlikte gelir ve şaşırtıcı sayıda durumu kapsar. Muhtemelen bazılarına zaten rastladınız:
ValueError: tür doğruyken değer geçersiz olduğunda, örneğin int("hello").
TypeError: bir işlemi yanlış tür üzerinde kullanmaya çalıştığınızda, örneğin bir metin ile sayıyı toplamak gibi.
ZeroDivisionError: tahmin ettiğiniz gibi, sıfıra bölme.
FileNotFoundError: var olmayan bir dosyayı açmaya çalışmak.
KeyError: sözlükte bir anahtar eksik olduğunda.
Bunlar kullanışlıdır ve çoğu betik veya uygulamada fazlasıyla yeterlidir. Ancak bazen daha açıklayıcı, projenizin dünyasında anlamlı olan bir şey yükseltmek isteyebilirsiniz; sadece Python'da değil.
Diyelim ki çevrimiçi siparişleri işleyen bir uygulama yazıyorsunuz ve kullanıcı stokta olmayan bir şeyi almaya çalıştığında bir hata yükseltmek istiyorsunuz. ValueError kullanabilirsiniz ama bu biraz genel kalır. Kodunuzu okuyan bir sonraki kişiye ne olduğunu söylemez.
İşte özel istisnaların parladığı yer.
classOutOfStockError(Exception):passdefcheck_inventory(product_id):ifnot in_stock(product_id):raise OutOfStockError(f"Product {product_id} is out of stock.")Altyapı:
Özel istisna oluşturarak, bir anlam katmanı ekliyorsunuz. Ayrıca kendinize daha fazla kontrol sağlıyorsunuz; yalnızca bu belirli durumu yakalayabilirsiniz:
try:
check_inventory("shirt-001")except OutOfStockError:print("Sorry, that item is sold out.")Altyapı:
Küçük bir şeydir ama özellikle daha büyük projelerde kodunuzu anlamayı ve sürdürmeyi kolaylaştırır. Ve günlükleme ve izleme ile de iyi çalışır; özel istisna adlarını, belirsiz bir ValueError'dan çok daha kolay arayabilirsiniz.
Günlükleme, Yeniden Yükseltme ve İstisna Zincirleme
Hata ayıklarken şöyle bir an olur: bir yığın izi görür, ona bakar ve bir şeyin neden neden başarısız olduğunu anlamazsınız. İşte burada günlükleme devreye girer. Sadece hataları kaydetmekle ilgili değildir; gelecekteki size (veya ekibinize) neyin ters gittiğini bulmanız için ekmek kırıntıları vermekle ilgilidir.
Diyelim ki bir istisnayı yakalıyor ve yola devam etmeden önce kaydetmek istiyorsunuz:
import logging
logging.basicConfig(level=logging.ERROR)try:
do_something()except ValueError as e:
logging.error("Failed to do something: %s", e)raiseAltyapı:
Sondaki raise önemlidir, günlüğe kaydettikten sonra aynı istisnayı yeniden fırlatır. Onsuz, hatayı yutmuş olursunuz. Bazen bu kabul edilebilir, ama genellikle değildir.
Bir de raise from numarası var. Bu, bir hatayı ele alırken başka birini yükseltmeniz gerektiğinde ve orijinali kaybetmek istemediğinizde kullanılır. Python bunları zincirlemenize izin verir:
try:
connect_to_database()except TimeoutError as e:raise ConnectionError("Database unavailable.")from eAltyapı:
Böylece yığın izi tüm hikâyeyi anlatır. Yeni ConnectionError'ı alırsınız ama buna neden olan TimeoutError'ı da görürsünüz.
Orijinal hatayı bastırabilirsiniz (genellikle yapmamalısınız) şöyle:
raise ConnectionError("Just this error, nothing else.")fromNoneAltyapı:
Ancak iyi bir nedeniniz olmadıkça, tam zinciri korumak neyin ters gittiğini ve nasıl büyüdüğünü herkesin anlamasına yardımcı olur.
İstisna yakalamayı soyut olarak konuşmak bir şeydir, ama gerçek koddaki hâliyle gördüğünüzde taşlar yerine oturur.
Örneğin kullanıcı girdisini ele alalım. Komut satırı aracı ya da form doğrulayıcı yazmış herkese sorun: kullanıcılar en tuhaf şeyleri girer. Siz sayı istersiniz; birisi “twelve” yazar. Ya da bir telefon numarası yapıştırır. Ya da sadece Enter'a basar. Olur böyle şeyler.
Uzun bir “ya şöyle olursa” kontrolleri listesi yazmak yerine şunu yapabilirsiniz:
whileTrue:
user_input =input("Enter a number: ")try:
number =int(user_input)breakexcept ValueError:print("Try again with a whole number.")Altyapı:
Bu kod, çöp bir giriş aldığında paniklemez. Kullanıcıya tekrar denemesini söyler ve işler yoluna girene kadar döngüye devam eder. Her köşe durumu için if deyimleri yığmaktan çok daha temiz.
Dosyanın orada olup olmadığını kontrol etmeye gerek yok. Sadece açmayı deneyin ve başarısız olursa devam edin. Önceden kontrol etmeye kalksaydınız (os.path.exists()), biri kontrol ile açma arasında dosyayı silebilirdi. Bu bir yarış durumudur, hata ayıklamak isteyeceğiniz türden değil.
Ağ istekleri istisnalar için bir başka verimli alan. İnternetin her zaman uslu duracağına güvenemezsiniz. Sunucular çöker. Bağlantılar düşer. DNS başarısız olur. Dolayısıyla şöyle bir şey yapıyorsanız:
Şu RequestException taban sınıfı, requests'ın yükseltebileceği hemen her şeyi, zaman aşımlarından kötü yanıtlara kadar, uygun biçimde yakalar. Farklı şekilde ele almak istemiyorsanız on farklı except bloğu yazmanıza gerek yok.
Ve otomasyon betikleri ya da arka uç servisleri yazıyorsanız, kilit mantığı try‑except bloklarına sarmak, tek bir görevin başarısız olması ile tüm sistemin kararması arasındaki fark olabilir. Hataların kaydedilmesini, kurtarılabilir görevlerin yeniden denenmesini ve kurtarılamayanların, günlüklerinizi sonsuza dek kayan anlaşılmaz yığın izleriyle değil, temizce kapatılmasını istersiniz.
Python otomasyonu hakkında; temel kavramlar, kilit kütüphaneler, verilerle çalışma, yapay zekâ ile geliştirmeler ve en iyi uygulamalar dâhil bilgi edinmek için Python Otomasyonu: Kapsamlı Rehber eğitimimize göz atın.
Try-except Python İleri Kullanımlar
Artık muhtemelen try‑except'in ne kadar esnek olabileceğini gördünüz. Ama esneklik iki ucu keskin kılıçtır. Farkında olmadan yararlıdan özensize kaymak kolaydır. İşleri kontrol altında tutmanın yolu şöyle.
Belirli istisnaları yakalayın. Neyin ters gidebileceğini biliyorsanız, adını verin:
try:
result =int(data)except ValueError:# Only catches invalid numbers, not everything else under the sunAltyapı:
Çıplak except:'ten kaçının. Çok özel bir şeyi ele almıyorsanız bunu yapmayın. KeyboardInterrupt, SystemExit ve muhtemelen susturmak istemeyeceğiniz diğer şeyleri de yakalar.
else ve finally'i kodu daha net yaptıklarında kullanın. Sırf varlar diye zorlamayın. Kodunuzun normal akışı bir try içinde gömülüyorsa, belki onu bir else'e taşıyın.
try bloklarınızı küçük tutun. Ne kadar çok şey eklerseniz hataya hangi satırın sebep olduğunu anlamak o kadar zor olur. Yalnızca başarısız olabilecek kısmı sarın.
Özellikle üretimdeyken hataları gerektiğinde kaydedin. Çökmüyor olsanız bile neyin (ve ne zaman) başarısız olduğunu bilmek, daha sonra hata ayıklamayı çok daha kolaylaştırır.
Özel istisnalar şart değildir ama yardımcı olurlar. Uygulamaya özgü sorunlarınız varsa, kendi hatalarınızı tanımlayın. Günlükleri daha okunabilir, kodunuzu daha kendini açıklayan hâle getirebilirler.
Son bir şey: istisnaları, daha iyi bir yol olmadıkça, akış kontrolü için kullanmayın. “Bunu dene; başarısız olursa şunu yap” gibi mantık yazmak cazip gelebilir, ama bu sık sık olmasını beklediğiniz bir şeyse muhtemelen daha temiz bir yol vardır.
Sonuç
Bu makale boyunca açıkladığım gibi, istisna yakalama sadece çökmeleri önlemekle ilgili değildir. Sorun bekleyen, bunu abartmadan ele alan ve devam eden ya da mantıklı bir şekilde kapanan kod yazmakla ilgilidir. Bu, kullanıcının yardımcı bir mesaj alması ile uzun, okunamaz bir yığın iziyle terminale geri atılması arasındaki farktır.
İstisneler hakkında daha fazlasını, uygulamalı alıştırmalarla öğrenmek için OOP in Python kursumuzdakiPython'da İstisna Yakalama bölümünü şiddetle tavsiye ederim.
Python try-except SSS
Python’da bir hata ile bir istisna arasındaki fark nedir?⌄
Bir hata genellikle Python'un kodunuzu başlatmasını bile engelleyen bir sorunu ifade eder; eksik iki nokta üst üste veya bir anahtar sözcükte yazım hatası gibi. Bunlar sözdizimi hatalarıdır. Bir istisna ise kod çalışırken ortaya çıkar; örneğin sıfıra bölmeyi denemek veya var olmayan bir dosyayı açmak gibi. İstisnalar yakalanabilir ve ele alınabilir, böylece programınız çökmez.
Python’da çıplak except kullanmak kötü müdür?⌄
Evet, çoğu durumda. Çıplak bir except her şeyi yakalar; klavye kesmeleri veya sistem çıkış sinyalleri gibi yakalamak istemediğiniz şeyler de dâhil. Bu da hata ayıklamayı zorlaştırır. ValueError veya FileNotFoundError gibi belirli istisnaları yakalamak daha iyidir, böylece tam olarak neyi ele aldığınızı bilirsiniz.
Try-except bloğunda else’i ne zaman kullanmalıyım?⌄
Else'i, yalnızca try bloğunda hiçbir istisna oluşmadığında bazı kodları çalıştırmak istediğinizde kullanın. Başarı yolundaki mantığınızı hata yakalama mantığından ayrı tutmaya yardımcı olur; bu da kodunuzu okumayı ve sürdürmeyi kolaylaştırabilir.
Zaten except bloğum varken finally’nin amacı nedir?⌄
finally ne olursa olsun çalışır; hata olsa da olmasa da. Temizlik için idealdir: dosyaları kapatmak, kaynakları serbest bırakmak, işlemleri geri almak vb. Bir hata olsa veya erken çıksanız bile finally yine çalışır.
Koşulları önce kontrol etmek yerine her zaman `try-except` mi kullanmalıyım?⌄
Her zaman değil, ama çoğu zaman sadece try etmek ve başarısız olursa hatayı catch etmek daha iyidir. Python geliştiricileri buna EAFP, “İzin İstemektense Affını İstemek Daha Kolaydır” der. Daha hızlıdır ve özellikle kontrol ile eylem arasında bir şeylerin değişebileceği durumlarda (ör. bir dosyanın silinmesi) belirli hatalardan kaçınır.
Algoritmalar, sistem tasarımı ve davranışsal senaryoları kapsayan bu temel sorularla teknik mülakat sürecine hakim olun. Uzman cevapları, kod örnekleri ve kanıtlanmış hazırlık stratejileri edinin.
Git deponuzu temiz tutmak için .gitignore’u nasıl kullanacağınızı öğrenin. Bu eğitim; temelleri, yaygın kullanım durumlarını ve başlamanıza yardımcı olacak pratik örnekleri kapsar!
Python kodu çalışma zamanında sorunlarla karşılaştığında, çoğu zaman bir istisna fırlatır. Ele alınmadan bırakılırsa, istisnalar programınızı çökertir. Ancak
try-exceptbloklarıyla bunları yakalayabilir, zarifçe toparlanabilir ve uygulamanızı çalışır durumda tutabilirsiniz.Bu eğitim istisnaların temelleri hakkında değil, bunu zaten Python'da İstisna ve Hata Yakalama rehberimizde ele aldık. Bunun yerine burada
try-exceptuygulamada nasıl kullanılır, bloklarınızı nasıl yapılandırırsınız, yaygın hatalardan nasıl kaçınırsınız ve gerçek dünyada kodunuzu daha güvenilir kılan en iyi uygulamaları nasıl uygularsınız gibi konulara derinlemesine bakacağız.Sonunda,
try-except'in nasıl çalıştığını değil, aynı zamanda onu Pythonik şekilde nasıl kullanacağınızı; açık, sürdürülebilir ve üretime hazır hata yakalama kodu yazmayı da anlayacaksınız.Python öğrenme yolculuğunuzda hâlâ ilerliyorsanız, tüm temel becerileri geliştirmenize yardımcı olacak Python Programlama Temelleri beceri rotasına göz atmanızı öneririm.
Neden try-except'e Odaklanalım?
Python'da hata yakalama temelde beklenmeyenle başa çıkabilen programlar tasarlamakla ilgilidir. Hataları ele almak için birçok araç olsa da,
try-exceptPython'un yaklaşımının bel kemiğidir.Peki neden bu kadar önemli?
try-exceptile kodunuz ilk sorunda çökmek yerine akıllıca tepki verir.ValueErroryakalamak içintry-exceptkullanabilir. Bir üretim sistemi ise hataları günlüğe kaydetmek, başarısız işlemleri yeniden denemek veya hata ayıklamayı kolaylaştıran özel istisnalar yükseltmek için kullanabilir.İşte bu yüzden bu makale
try-exceptüzerine odaklanıyor. Bunu ustalaşmak, yalnızca kusursuz koşullarda çalışan betikler ile sağlam, sürdürülebilir ve üretime hazır yazılımlar yazmak arasındaki farktır.Bir Try‑Except Bloğunun Anatomisi
En basit hâliyle:
Python,
trybloğu içinde bir hatayla karşılaştığında, programı çökertmek yerine eşleşenexceptbloğuna atlar.Bu deseni
elsevefinallyhükümleriyle de genişletebilirsiniz:İşte temel bir çalışma örneği:
excepthatayı ele alır, else yalnızca işler yolunda giderse çalışır ve finally, Ctrl‑C'ye bassanız veya çıksanız bile her zaman çalışır.Python'da kullanıcı girişi yakalamanın temellerini, basit istemlerden gelişmiş doğrulama ve hata yakalama tekniklerine kadar, Python Kullanıcı Girdisi: Yakalama, Doğrulama ve En İyi Uygulamalar eğitimimizle öğrenebilirsiniz.
Birden Fazla İstisnayı Ele Alma
Bazen tek bir
exceptyeterli olmaz. Farklı kod yolları farklı şekillerde başarısız olabilir ve çıplak bir except: ile her şeyi yakalamak pek yardımcı değildir; hataları gizleyebilir ve hata ayıklamayı bir baş ağrısına çevirebilir.Diyelim ki bir şeyi tamsayıya dönüştürmeye ve sonra bölmeye çalışıyorsunuz. İşte yapmamanız gereken:
Bu, değişken adlarında yazım hataları veya gerçek sorunlara işaret eden beklenmedik istisnalar gibi muhtemelen gizlemek istemediğiniz şeyler de dâhil olmak üzere her şeyi yakalar.
Bunun yerine, belirli olun:
Aynı şekilde ele alınması gereken birden fazla istisna türünüz varsa, bunları şu şekilde gruplayabilirsiniz:
Böylece, aynı bloğu tekrar tekrar kopyalamadan yine de nelerin ters gidebileceğini net biçimde belirtmiş olursunuz.
Bir de
except Exceptionvar, bu çıplak birexcept'ten iyidir ama hâlâ fazla geniştir. Beklediğiniz belirli hataları hedeflemek daha iyidir.else ve finally Bloklarını Kullanma
trybloğu içindeki kod başarıyla çalışır ve hiçbir istisna yükseltilmezse, Pythonelsebloğunu yürütür.Bu, istisna yakalama mantığınızı mutlu yolunuzdan ayırmanıza yardımcı olur ve okumayı kolaylaştırır.
Bir de
finallyvar. Ne olduğuyla ilgilenmez; ne olursa olsun çalışır. İstisna mı? Yine çalışır. İstisna yok mu? Yine çalışır. Program Ctrl‑C ile mi sonlandırıldı? Yine çalışır. Temizlik işleri için harikadır:Yalnız unutmayın, dosya hiç açılmadıysa
fvar olmamış olabilir, dikkatli olun. Dosyalarla çalışırken bunun yerine Python'un bağlam yöneticisini (with open(...) as f:) kullanabilirsiniz. Daha güvenlidir.Python'da
KeyErroristisnasını etkili bir şekilde ele almak için istisna yakalama ve hata önleme gibi temel teknikleri öğrenmek isterseniz, Python KeyError İstisnaları ve Nasıl Düzeltilir eğitimimizi öneririm.Python try-except En İyi Uygulamalar ve Yaygın Tuzaklar
Açık konuşalım:
try‑exceptblokları yazmak biraz sanattır. Doğru yapıldığında programınızın çökmesini engeller. Kötü yapıldığında ise hataları o kadar derine gömer ki, uygulamanız çöküp kullanıcılar şikâyet edene kadar fark etmezsiniz.İşte edinmeye değer bazı alışkanlıklar:
trybloklarını dar tutun. Yüzlerce satır kodu tek bir try içine sarmalayın demiyoruz. Bu yalnızca soruna neyin sebep olduğunu bilmeyi zorlaştırır. Bunun yerine, yalnızca başarısız olabilecek kodu sarmalayın:Eylemi yapmadan önce koşulları kontrol etmekten kaçının; hatayı yakalamak daha kolaysa doğrudan deneyin. Python bunu şöyle adlandırır: EAFP, Easier to Ask Forgiveness than Permission. Bir dosyanın var olup olmadığını kontrol edip sonra açıyorsanız, yarış durumu yaratıyorsunuz. Bunun yerine:
Bu desen, dosyanın kontrol ile açma çağrısı arasında ortadan kaybolabileceği yaygın bir sorundan kaçınır. Sadece işi deneyin. Başarısız olursa, hatayı yakalayın.
Ayrıca, her şeyi yakalayıp hiçbir şey yapmayarak hataları susturmaktan kaçının. Bunu yapmayın:
Gerçekten ne yaptığınızı bilmiyorsanız, bu hataların saklanıp çoğalacağı yerdir. Mutlaka susturmanız gerekiyorsa, spesifik olun:
Ve hataları bir yere kaydedin. Tamamen yutmak, gelecekte neyin yanlış gittiğine dair hiçbir fikriniz olmayacağı anlamına gelir.
Yerleşik ve Özel İstisnalar
Python, pek çok yerleşik istisna ile birlikte gelir ve şaşırtıcı sayıda durumu kapsar. Muhtemelen bazılarına zaten rastladınız:
ValueError: tür doğruyken değer geçersiz olduğunda, örneğinint("hello").TypeError: bir işlemi yanlış tür üzerinde kullanmaya çalıştığınızda, örneğin bir metin ile sayıyı toplamak gibi.ZeroDivisionError: tahmin ettiğiniz gibi, sıfıra bölme.FileNotFoundError: var olmayan bir dosyayı açmaya çalışmak.KeyError: sözlükte bir anahtar eksik olduğunda.Bunlar kullanışlıdır ve çoğu betik veya uygulamada fazlasıyla yeterlidir. Ancak bazen daha açıklayıcı, projenizin dünyasında anlamlı olan bir şey yükseltmek isteyebilirsiniz; sadece Python'da değil.
Diyelim ki çevrimiçi siparişleri işleyen bir uygulama yazıyorsunuz ve kullanıcı stokta olmayan bir şeyi almaya çalıştığında bir hata yükseltmek istiyorsunuz.
ValueErrorkullanabilirsiniz ama bu biraz genel kalır. Kodunuzu okuyan bir sonraki kişiye ne olduğunu söylemez.İşte özel istisnaların parladığı yer.
Özel istisna oluşturarak, bir anlam katmanı ekliyorsunuz. Ayrıca kendinize daha fazla kontrol sağlıyorsunuz; yalnızca bu belirli durumu yakalayabilirsiniz:
Küçük bir şeydir ama özellikle daha büyük projelerde kodunuzu anlamayı ve sürdürmeyi kolaylaştırır. Ve günlükleme ve izleme ile de iyi çalışır; özel istisna adlarını, belirsiz bir
ValueError'dan çok daha kolay arayabilirsiniz.Günlükleme, Yeniden Yükseltme ve İstisna Zincirleme
Hata ayıklarken şöyle bir an olur: bir yığın izi görür, ona bakar ve bir şeyin neden neden başarısız olduğunu anlamazsınız. İşte burada günlükleme devreye girer. Sadece hataları kaydetmekle ilgili değildir; gelecekteki size (veya ekibinize) neyin ters gittiğini bulmanız için ekmek kırıntıları vermekle ilgilidir.
Diyelim ki bir istisnayı yakalıyor ve yola devam etmeden önce kaydetmek istiyorsunuz:
Sondaki
raiseönemlidir, günlüğe kaydettikten sonra aynı istisnayı yeniden fırlatır. Onsuz, hatayı yutmuş olursunuz. Bazen bu kabul edilebilir, ama genellikle değildir.Bir de
raise fromnumarası var. Bu, bir hatayı ele alırken başka birini yükseltmeniz gerektiğinde ve orijinali kaybetmek istemediğinizde kullanılır. Python bunları zincirlemenize izin verir:Böylece yığın izi tüm hikâyeyi anlatır. Yeni
ConnectionError'ı alırsınız ama buna neden olanTimeoutError'ı da görürsünüz.Orijinal hatayı bastırabilirsiniz (genellikle yapmamalısınız) şöyle:
Ancak iyi bir nedeniniz olmadıkça, tam zinciri korumak neyin ters gittiğini ve nasıl büyüdüğünü herkesin anlamasına yardımcı olur.
Python'da günlüklemenin temellerini Python'da Günlükleme Eğitimi ile öğrenebilirsiniz.
Gerçek Dünya Örnekleri ve Kullanım Alanları
İstisna yakalamayı soyut olarak konuşmak bir şeydir, ama gerçek koddaki hâliyle gördüğünüzde taşlar yerine oturur.
Örneğin kullanıcı girdisini ele alalım. Komut satırı aracı ya da form doğrulayıcı yazmış herkese sorun: kullanıcılar en tuhaf şeyleri girer. Siz sayı istersiniz; birisi “twelve” yazar. Ya da bir telefon numarası yapıştırır. Ya da sadece Enter'a basar. Olur böyle şeyler.
Uzun bir “ya şöyle olursa” kontrolleri listesi yazmak yerine şunu yapabilirsiniz:
Bu kod, çöp bir giriş aldığında paniklemez. Kullanıcıya tekrar denemesini söyler ve işler yoluna girene kadar döngüye devam eder. Her köşe durumu için if deyimleri yığmaktan çok daha temiz.
Bir diğeri: var olmayabilecek bir dosyadan okuma.
Dosyanın orada olup olmadığını kontrol etmeye gerek yok. Sadece açmayı deneyin ve başarısız olursa devam edin. Önceden kontrol etmeye kalksaydınız (
os.path.exists()), biri kontrol ile açma arasında dosyayı silebilirdi. Bu bir yarış durumudur, hata ayıklamak isteyeceğiniz türden değil.Ağ istekleri istisnalar için bir başka verimli alan. İnternetin her zaman uslu duracağına güvenemezsiniz. Sunucular çöker. Bağlantılar düşer. DNS başarısız olur. Dolayısıyla şöyle bir şey yapıyorsanız:
Şu
RequestExceptiontaban sınıfı,requests'ın yükseltebileceği hemen her şeyi, zaman aşımlarından kötü yanıtlara kadar, uygun biçimde yakalar. Farklı şekilde ele almak istemiyorsanız on farklıexceptbloğu yazmanıza gerek yok.Ve otomasyon betikleri ya da arka uç servisleri yazıyorsanız, kilit mantığı try‑except bloklarına sarmak, tek bir görevin başarısız olması ile tüm sistemin kararması arasındaki fark olabilir. Hataların kaydedilmesini, kurtarılabilir görevlerin yeniden denenmesini ve kurtarılamayanların, günlüklerinizi sonsuza dek kayan anlaşılmaz yığın izleriyle değil, temizce kapatılmasını istersiniz.
Python otomasyonu hakkında; temel kavramlar, kilit kütüphaneler, verilerle çalışma, yapay zekâ ile geliştirmeler ve en iyi uygulamalar dâhil bilgi edinmek için Python Otomasyonu: Kapsamlı Rehber eğitimimize göz atın.
Try-except Python İleri Kullanımlar
Artık muhtemelen
try‑except'in ne kadar esnek olabileceğini gördünüz. Ama esneklik iki ucu keskin kılıçtır. Farkında olmadan yararlıdan özensize kaymak kolaydır. İşleri kontrol altında tutmanın yolu şöyle.Belirli istisnaları yakalayın. Neyin ters gidebileceğini biliyorsanız, adını verin:
Çıplak
except:'ten kaçının. Çok özel bir şeyi ele almıyorsanız bunu yapmayın.KeyboardInterrupt,SystemExitve muhtemelen susturmak istemeyeceğiniz diğer şeyleri de yakalar.elsevefinally'i kodu daha net yaptıklarında kullanın. Sırf varlar diye zorlamayın. Kodunuzun normal akışı birtryiçinde gömülüyorsa, belki onu birelse'e taşıyın.trybloklarınızı küçük tutun. Ne kadar çok şey eklerseniz hataya hangi satırın sebep olduğunu anlamak o kadar zor olur. Yalnızca başarısız olabilecek kısmı sarın.Özellikle üretimdeyken hataları gerektiğinde kaydedin. Çökmüyor olsanız bile neyin (ve ne zaman) başarısız olduğunu bilmek, daha sonra hata ayıklamayı çok daha kolaylaştırır.
Özel istisnalar şart değildir ama yardımcı olurlar. Uygulamaya özgü sorunlarınız varsa, kendi hatalarınızı tanımlayın. Günlükleri daha okunabilir, kodunuzu daha kendini açıklayan hâle getirebilirler.
Son bir şey: istisnaları, daha iyi bir yol olmadıkça, akış kontrolü için kullanmayın. “Bunu dene; başarısız olursa şunu yap” gibi mantık yazmak cazip gelebilir, ama bu sık sık olmasını beklediğiniz bir şeyse muhtemelen daha temiz bir yol vardır.
Sonuç
Bu makale boyunca açıkladığım gibi, istisna yakalama sadece çökmeleri önlemekle ilgili değildir. Sorun bekleyen, bunu abartmadan ele alan ve devam eden ya da mantıklı bir şekilde kapanan kod yazmakla ilgilidir. Bu, kullanıcının yardımcı bir mesaj alması ile uzun, okunamaz bir yığın iziyle terminale geri atılması arasındaki farktır.
İstisneler hakkında daha fazlasını, uygulamalı alıştırmalarla öğrenmek için OOP in Python kursumuzdaki Python'da İstisna Yakalama bölümünü şiddetle tavsiye ederim.