PyCharm IDE kullanılırken, except:
istisna türü olmadan kullanılması, bu istisna cümlesinin olduğu konusunda IDE'den bir hatırlatıcı tetikler Too broad
.
Bu tavsiyeyi görmezden gelmeli miyim? Yoksa her zaman istisna türünü belirtmek Pythonic mi?
PyCharm IDE kullanılırken, except:
istisna türü olmadan kullanılması, bu istisna cümlesinin olduğu konusunda IDE'den bir hatırlatıcı tetikler Too broad
.
Bu tavsiyeyi görmezden gelmeli miyim? Yoksa her zaman istisna türünü belirtmek Pythonic mi?
Yanıtlar:
Açık bir istisna türü belirtmek neredeyse her zaman daha iyidir. Çıplak bir except:
cümle kullanırsanız, yakalamayı bekledikleriniz dışındaki istisnaları yakalayabilirsiniz - bu, hataları gizleyebilir veya beklediğiniz şeyi yapmadıklarında programlarda hata ayıklamayı zorlaştırabilir.
Örneğin, bir veritabanına bir satır ekliyorsanız, satırın zaten var olduğunu gösteren bir istisna yakalamak isteyebilirsiniz, böylece bir güncelleme yapabilirsiniz.
try:
insert(connection, data)
except:
update(connection, data)
Çıplak belirtirseniz except:
, veritabanı sunucusunun düştüğünü gösteren bir soket hatası da yakalayabilirsiniz. En iyisi, yalnızca nasıl başa çıkacağınızı bildiğiniz istisnaları yakalamaktır - programın istisna noktasında başarısız olması, devam etmekten ancak beklenmedik şekillerde davranmaktan daha iyidir.
Çıplak kullanmak isteyebileceğiniz bir except:
durum, bir ağ sunucusu gibi her zaman çalışıyor olmanız gereken bir programın en üst düzeyindedir. Ama sonra, istisnaları kaydetmek için çok dikkatli olmalısınız, aksi takdirde neyin yanlış gittiğini anlamak imkansız olacaktır. Temel olarak, bunu yapan bir programda en fazla bir yer olmalıdır.
Tüm bunların doğal bir sonucu, kodunuzun raise Exception('some message')
istemci kodunu kullanmaya zorladığı için except:
(ya except Exception:
da neredeyse o kadar kötü) asla yapmaması gerektiğidir . Sinyal vermek istediğiniz soruna özel bir istisna tanımlamalısınız (belki ValueError
veya gibi bazı yerleşik istisna alt sınıflarından miras alabilirsiniz TypeError
). Veya belirli bir yerleşik istisna oluşturmalısınız. Bu, kodunuzun kullanıcılarının yalnızca ele almak istedikleri istisnaları yakalama konusunda dikkatli olmalarını sağlar.
except:
aynı zamanda yakalar (diğer birçok şeyin yanı sıra) NameError
ve AttributeError
bu nedenle try
bloktaki bir şeyi yanlış yazarsanız (örneğin, "ekleme" işleviniz aslında çağrılır insert_one
çünkü birisi tutarlılığa olması gerektiği kadar değer vermedi) her zaman sessizce dener update()
.
main()
)?
except Exception:
yakalayacak NameError
ve AttributeError
çok. Bu except:
kadar kötü yapan şey, yakalanmayan işleri yakalamasıdır, örneğin SystemExit
(aradığınızda exit
veya sys.exit
şimdi amaçlanan bir çıkışı engellediniz) ve KeyboardInterrupt
(yine, kullanıcı vurursa Ctrl-C
, muhtemelen istemezsiniz) sadece onlara inat için koşmaya devam etmek). Sadece ikincisi yakalamak gerçekten mantıklıdır ve açıkça yakalanmalıdır. En azından except Exception:
bu ikisinin normal şekilde yayılmasına izin verin.
Tercümanın size verdiği tavsiyeleri görmezden gelmemelisiniz.
Python için PEP-8 Stil Kılavuzundan:
İstisnaları yakalarken, bir bare external: clause kullanmak yerine, mümkün olduğunda belirli istisnalardan bahsedin.
Örneğin, şunu kullanın:
try:
import platform_specific_module
except ImportError:
platform_specific_module = None
Bare exclude: cümlesi, SystemExit ve KeyboardInterrupt istisnalarını yakalayarak, bir programı Control-C ile kesmeyi zorlaştırır ve diğer sorunları gizleyebilir. Program hatalarını işaret eden tüm istisnaları yakalamak istiyorsanız, Exception dışında kullanın: (bare hariç, BaseException hariç :) ile eşdeğerdir.
İyi bir pratik kural, çıplak 'hariç' cümlelerinin kullanımını iki durumla sınırlandırmaktır:
İstisna işleyici, izlemeyi yazdıracak veya günlüğe kaydedecekse; en azından kullanıcı bir hatanın meydana geldiğinin farkında olacaktır. Kodun bazı temizleme çalışması yapması gerekiyorsa, ancak daha sonra istisnanın yükseltme ile yukarı doğru yayılmasına izin verirse. try ... nihayet bu davayı halletmenin daha iyi bir yolu olabilir.
Bu Python'a özgü değil.
İstisnaların tüm amacı, sorunu mümkün olduğu kadar ortaya çıktığı yere yakın ele almaktır.
Bu nedenle, istisnai durumlarda sorunu ve çözümü "yan yana" tetikleyebilecek kodu saklarsınız.
Mesele şu ki, bir kod parçası tarafından atılabilecek tüm istisnaları bilemezsiniz. Tek bildiğiniz, eğer istisna bulunmayan bir dosya ise, o zaman onu yakalayabilir ve kullanıcıdan işlevi yapan veya iptal eden bir tane almasını isteyebilirsiniz.
Bunu deneyin yakalamaya koyarsanız, dosya yordamınızda hangi sorun olursa olsun (salt okunur, izinler, UAC, gerçekte bir pdf değil, vb.), Her biri dosyanıza düşecektir catch ve kullanıcınız "ama orada, bu kod saçmalık" diye bağırıyor
Şimdi her şeyi yakalayabileceğiniz birkaç durum var, ancak bilinçli olarak seçilmeleri gerekiyor.
Yakalanırlar, bazı yerel eylemleri geri alırlar (örneğin, bir kaynak oluşturmak veya kilitlemek, (örneğin yazmak için diskte bir dosya açmak), ardından daha yüksek bir düzeyde ilgilenilmek üzere istisnayı tekrar atarsınız)
Diğeri, neden yanlış gittiğini umursamıyorsun. Örneğin baskı. Yazıcınızda bir sorun var, lütfen düzeltin ve bu yüzden uygulamayı sonlandırmayın demek için her yönden bir yakalamaya sahip olabilirsiniz. Buna benzer bir boşuna, eğer kodunuz bir çeşit zamanlama kullanarak bir dizi ayrı görevi yerine getirirse, tüm şeyin ölmesini istemezsiniz, çünkü görevlerden biri başarısız olur.
Not Yukarıdakileri yaparsanız, bir tür istisna günlüğü öneremem, örneğin, son derece yeterli, günlük sonunu yakalamaya çalışın.
Bununla birlikte örneğin Control-C'yi de yakalayacaksınız, bu yüzden tekrar "atmadan" yapmayın. Ancak, bu durumda "nihayet" seçeneğini tercih etmelisiniz.
Her zaman gibi catch istemiyorum birçok türü vardır, istisna türünü belirtmek SyntaxError
, KeyboardInterrupt
, MemoryError
vb
except Exception:
yakalamak istemediğimiz yukarıdaki türleri kullanmaktan kaçınır mıyız?
except Exception
iyidir.
except Exception
yakalar SyntaxError
ve MemoryError
çünkü bu onların temel sınıfıdır. KeyboardInterrupt
, SystemExit
(tarafından büyütüldü sys.exit()
) yakalanmadı (bunlar hemen BaseException alt sınıflarıdır)
Yazısız dışında kullandığım yerler
Kontrol edilmeyen istisnalar için kodumdaki ana kullanım budur
Her zaman bunu eklerim, böylece üretim kodu yığın izlerini yaymaz
Bunu yapmanın iki yolu var:
Bu şekilde tercih ediyorum, hangi istisnaların uygun şekilde yakalanması gerektiğini tespit etmeyi daha kolay buluyorum: Daha yüksek bir seviye tarafından daha düşük seviyeli bir istisna kaydedildiğinde sorunu daha iyi "görüyorum"
Bazı iş arkadaşları, "ait oldukları" alt düzey işlevlerde daha düşük düzeydeki istisnaları koruduğu için bu yolu tercih eder.
Bunu dene:
try:
#code
except ValueError:
pass
Cevabı bu bağlantıdan aldım, eğer başka biri bu sorunla karşılaştıysa kontrol edin