Doğru tahmin ettiğiniz gibi, bunun iki tarafı vardır: Herhangi bir istisna türü belirterek herhangi bir hatayı yakalamak except
ve herhangi bir işlem yapmadan iletmek.
Benim açıklamam “biraz” daha uzun - bu yüzden tl; dr bunu yıkıyor:
- Herhangi bir hata yakalama . Her zaman hangi istisnaları kurtarmaya hazır olduğunuzu belirtin ve yalnızca bunları istisna edin.
- Bloklar dışında geçmekten kaçının . Açıkça istenmedikçe, bu genellikle iyi bir işaret değildir.
Ama ayrıntılara girelim:
Yakalamak etmeyin herhangi bir hata
Bir try
blok kullanırken , genellikle bunu yaparsınız çünkü bir istisna oluşma şansı olduğunu bilirsiniz. Bu nedenle, neyin kırılabileceği ve hangi istisnaların atılabileceği hakkında da yaklaşık bir fikriniz var . Bu gibi durumlarda, bir istisna yakalarsınız, çünkü ondan olumlu şekilde kurtulabilirsiniz . Bu, istisna için hazır olduğunuz ve bu istisna durumunda izleyeceğiniz alternatif bir planınızın olduğu anlamına gelir.
Örneğin, kullanıcıdan bir sayı girmesini istediğinizde, a'yı int()
yükseltebilecek olan girişi dönüştürebilirsiniz ValueError
. Kullanıcıdan tekrar denemesini isteyerek kolayca kurtarabilirsiniz, bu nedenle ValueError
kullanıcıyı yakalamak ve tekrar istemek uygun bir plan olacaktır. Farklı bir örnek, bir dosyadan bazı yapılandırmaları okumak istiyorsanız ve bu dosyanın mevcut olmamasıdır. Bu bir yapılandırma dosyası olduğundan, yedek olarak bazı varsayılan yapılandırmalarınız olabilir, bu nedenle dosya tam olarak gerekli değildir. Dolayısıyla FileNotFoundError
, varsayılan yapılandırmayı yakalamak ve uygulamak, burada iyi bir plan olacaktır. Şimdi her iki durumda da, beklediğimiz çok özel bir istisnamız var ve ondan kurtulmak için eşit derecede spesifik bir planımız var. Bunun gibi, her durumda, biz açıkça sadece except
belli olduğunu istisna.
Bununla birlikte, eğer her şeyi yakalayacak olsaydık, - iyileşmeye hazır olduğumuz istisnalara ek olarak - beklemediğimiz ve gerçekten kurtulamadığımız istisnalar alma şansımız da vardır; veya iyileşmemelidir.
Yukarıdan yapılandırma dosyası örneğini ele alalım. Eksik bir dosya olması durumunda, varsayılan yapılandırmamızı uyguladık ve daha sonra yapılandırmayı otomatik olarak kaydetmeye karar verebiliriz (bir dahaki sefere dosya var). Şimdi bir IsADirectoryError
veya birPermissionError
yerine. Bu gibi durumlarda, muhtemelen devam etmek istemiyoruz; yine de varsayılan yapılandırmamızı uygulayabiliriz, ancak daha sonra dosyayı kaydedemeyiz. Ve muhtemelen kullanıcının da özel bir yapılandırmaya sahip olması gerekiyordu, bu yüzden varsayılan değerleri kullanmak muhtemelen istenmiyor. Bu yüzden kullanıcıya derhal bunu anlatmak ve muhtemelen programın yürütülmesini iptal etmek istiyoruz. Ancak bu, bazı küçük kod bölümlerinin derinliklerinde yapmak istediğimiz bir şey değildir; bu uygulama düzeyinde önemli bir şeydir, bu yüzden en üstte ele alınmalıdır - bu yüzden istisnanın patlamasına izin verin.
Başka bir basit örnek de Python 2 deyimleri belgesinde belirtilmiştir. Burada, kodda kırılmasına neden olan basit bir yazım hatası vardır. Biz yakalamak Çünkü her özel durum, biz de yakalamak NameError
s ve SyntaxError
s . Her ikisi de programlama sırasında hepimizin başına gelen hatalar; ve her ikisi de kodu gönderirken kesinlikle dahil etmek istemediğimiz hatalardır. Ancak bunları da yakaladığımız için, orada meydana geldiklerini bile bilmeyeceğiz ve doğru bir şekilde hata ayıklamak için herhangi bir yardımı kaybetmeyeceğiz.
Ancak, muhtemelen hazırlıklı olmadığımız daha tehlikeli istisnalar da var. Örneğin SystemError genellikle nadiren gerçekleşen ve gerçekten planlayamadığımız bir şeydir; daha karmaşık bir şey olduğu, şu anki görevi sürdürmemizi engelleyen bir şey olduğu anlamına gelir.
Her durumda, kodun küçük ölçekli bir bölümünde her şeye hazırlıklı olmanız pek olası değildir, bu yüzden sadece hazır olduğunuz istisnaları yakalamanız gereken yer burasıdır. Bazı insanlar en azından av önermek Exception
o gibi şeyler içermez olarak SystemExit
ve KeyboardInterrupt
hangi tasarımı ile başvurunuzu sonlandırmak için vardır, ama bu hala çok belirsiz olduğunu iddia ediyorum. Ben şahsen alıcı kabul tek yer yoktur Exception
sadece ya herhangiistisnadır ve bu, hazırlanmadığımız herhangi bir istisnayı günlüğe kaydetmek için tek bir amacı olan tek bir global uygulama düzeyinde istisna işleyicisidir. Bu şekilde, beklenmedik istisnalar hakkında hala daha fazla bilgi tutabiliriz; bu, kodumuzu açık bir şekilde ele almak için (onlardan kurtarabilirsek) veya - bir hata durumunda - emin olmak için test senaryoları oluşturmak için kullanabileceğimiz kodları genişletmek için kullanabiliriz. bir daha olmayacak. Ama elbette, bu sadece zaten beklediğimiz istisnaları yakalarsak işe yarar, bu yüzden beklemediklerimiz doğal olarak kabarır.
Bloklar dışında geçiş yapmaktan kaçının
Açık bir şekilde belirli istisnaların küçük bir seçimini yakalarken, hiçbir şey yapmadan iyi olacağımız birçok durum vardır. Bu gibi durumlarda, sadece sahip except SomeSpecificException: pass
olmak iyidir. Çoğu zaman, kurtarma işlemi ile ilgili bazı kodlara ihtiyacımız olduğu için (yukarıda belirtildiği gibi) bu durum böyle değildir. Bu, örneğin, eylemi tekrar deneyen veya bunun yerine varsayılan bir değer ayarlayan bir şey olabilir.
Eğer durum böyle değilse, örneğin, kodumuz başarılı olana kadar tekrarlayacak şekilde yapılandırılmış olduğundan, sadece geçmek yeterince iyidir. Yukarıdaki örneğimizi dikkate alarak kullanıcıdan bir sayı girmesini isteyebiliriz. Kullanıcıların istediğimiz şeyi yapmayı sevmediklerini bildiğimiz için, ilk etapta bir döngüye koyabiliriz, böylece şöyle görünebilir:
def askForNumber ():
while True:
try:
return int(input('Please enter a number: '))
except ValueError:
pass
Hiçbir istisna atılıncaya kadar denemeye devam ettiğimiz için, hariç blokta özel bir şey yapmamıza gerek yok, bu yüzden bu iyi. Ancak elbette, en azından kullanıcıya, girişi neden tekrarlamak zorunda olduğunu söylemek için bazı hata mesajları göstermek istediğimizi iddia edebiliriz.
Diğer birçok durumda, sadece bir anı geçmek except
, yakaladığımız istisna için gerçekten hazırlıklı olmadığımızın bir işaretidir. Bu istisnalar basit ( ValueError
veya gibi TypeError
) değilse ve geçebilmemizin nedeni açık değilse, sadece geçmekten kaçının. Gerçekten yapacak bir şey yoksa (ve bundan kesinlikle eminseniz), neden böyle olduğunu bir yorum eklemeyi düşünün; tersi durumda, gerçekten bazı kurtarma kodlarını içermek için hariç bloğunu genişletin.
except: pass
En kötü suçlu her ikisinin birleşimidir. Gönlü yakaladığı yönünde bu araçlar herhangi kesinlikle bunun için hazır olmadıkları halde hata ve biz de bu konuda hiçbir şey yoktur. Sen en azından hatayı giriş yapmak istiyor ve ayrıca muhtemelen hala uygulamayı sonlandırmak için tekrar yükseltme (belirli bir MemoryError sonra normal şekilde devam edebilir düşüktür). Ancak geçmek sadece uygulamayı biraz canlı tutmakla kalmaz (elbette yakaladığınız yere bağlı olarak), aynı zamanda tüm bilgileri de atar ve hatayı keşfetmeyi imkansız hale getirir - bu, onu keşfeden kişi değilseniz özellikle doğrudur.
Sonuç olarak: Sadece gerçekten beklediğiniz ve iyileşmeye hazır istisnaları yakalayın; diğerlerinin tümü ya düzeltmeniz gereken hatalardır ya da yine de hazırlıklı olmadığınız bir şeydir. Gerçekten onlar hakkında bir şey yapmanız gerekmiyorsa, belirli istisnaları geçmek iyidir. Diğer tüm durumlarda, bu sadece bir varsayım ve tembel olmanın bir işaretidir. Ve kesinlikle bunu düzeltmek istiyorsun.
logging
Üretim sırasında akışlarını önlemek için DEBUG düzeyinde modülü kullanın , ancak geliştirme sırasında hazır bulundurun.