Neden “hariç: geçmek” kötü bir programlama uygulamasıdır?


324

Kullanımının nasıl except: passengellendiği konusunda diğer Stack Overflow sorularıyla ilgili yorumları sık sık görüyorum . Bu neden kötü? Bazen sadece hataların ne olduğu umurumda değil ve sadece kodla devam etmek istiyorum.

try:
    something
except:
    pass

Bir except: passbloğu kullanmak neden kötü? Kötü yapan nedir? Sanki ben aslında var passbir hata veya ki ben exceptherhangi bir hata?


1
En azından, günlüğe kaydetmenizi öneririm, böylece hangi sorunları görmezden geldiğinizi bilirsiniz. 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.
pcurry

Yanıtlar:


346

Doğru tahmin ettiğiniz gibi, bunun iki tarafı vardır: Herhangi bir istisna türü belirterek herhangi bir hatayı yakalamak exceptve herhangi bir işlem yapmadan iletmek.

Benim açıklamam “biraz” daha uzun - bu yüzden tl; dr bunu yıkıyor:

  1. Herhangi bir hata yakalama . Her zaman hangi istisnaları kurtarmaya hazır olduğunuzu belirtin ve yalnızca bunları istisna edin.
  2. 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 tryblok 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 ValueErrorkullanı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 IsADirectoryErrorveya birPermissionErroryerine. 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 NameErrors ve SyntaxErrors . 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 Exceptiono gibi şeyler içermez olarak SystemExitve KeyboardInterrupthangi 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 Exceptionsadece 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: passolmak 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 ( ValueErrorveya 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.


1
"En azından hatayı günlüğe kaydetmek ve uygulamayı hala sonlandırmak için yeniden yükseltmek istiyorsunuz". Yakaladıktan sonra bile kabarmaya devam etmesine izin vermek için bir istisnayı nasıl "yeniden" göstereceğinizi gösterebilir misiniz? Bu, istisnanın uygulamayı sonlandırmaya zorlamasına izin verirken bazı özel hata mesajlarını eklemem için yararlı görünüyor.
Gabriel Staples

1
Bu açıklığa kavuşturmaya yardımcı olur: battaniyeyi kullanırlar except, ancak raiseistisna balonunun serbest kalmasına izin vermek ve uygulamayı sonlandırmak için hiçbir argüman olmadan çağrı yaparlar. Beğendim : ianbicking.org/blog/2007/09/re-raising-exceptions.html . Battaniyeyi kullanmama kuralına sağlam bir istisna gibi görünüyor except.
Gabriel Staples

1
@GabrielStaples Evet, yakalanan bir istisna kullanılarak yeniden düşünülebilir raise. Bu işlemi istisnayı günlüğe kaydetmek için genellikle uygulamanızın içindeki birkaç yerde yaparsınız.
dürtmek

Bu harika, bloklar dışında geçmekten kaçının. Bunun, özellikle başkaları için daha anlaşılır görünen şeyleri yapmasını söyleyebilirim. Kodunuzu incelemek ve bloğu sorgulayıp sorgulamadıklarını görmek için ikinci bir python gözleri seti alın. Okunabilirlik önemlidir.
radtek

262

Burada ana sorun, tüm ve herhangi bir hatayı yok sayar: Bellek yetersiz, CPU yanıyor, kullanıcı durdurmak istiyor, program çıkmak istiyor, Jabberwocky kullanıcıları öldürüyor.

Bu çok fazla. Kafanızda, "Bu ağ hatasını yoksaymak istiyorum" diye düşünüyorsunuz. Bir şey varsa beklenmeyen ters giderse, sonra kod sessizce devam eder ve tamamen öngörülemeyen biçimlerde sonları kimsenin ayıklamak, dikkat.

Bu yüzden kendinizi sadece bazı hataları görmezden gelmeniz ve geri kalanının geçmesine izin vermelisiniz.


75

Sahte kodunuzu tam anlamıyla çalıştırmak herhangi bir hata bile vermez:

try:
    something
except:
    pass

a atmak yerine son derece geçerli bir kod parçası gibi NameError. Umarım istediğin bu değildir.


51

Neden “hariç: geçmek” kötü bir programlama uygulamasıdır?

Bu neden kötü?

try:
    something
except:
    pass

Bu da dahil olmak üzere, mümkün olan her türlü durum yakalar GeneratorExit, KeyboardInterruptve SystemExit- muhtemelen catch istemeyen istisnalar vardır ki. Yakalamakla aynı BaseException.

try:
    something
except BaseException:
    pass

Belgelerin eski sürümleri şunları söylüyor :

Python'daki her hata bir istisna oluşturduğundan, kullanmak except:birçok programlama hatasını çalışma zamanı sorunlarına benzetebilir, bu da hata ayıklama işlemini engeller.

Python İstisna Hiyerarşisi

Bir üst istisna sınıfını yakalarsanız, tüm alt sınıflarını da yakalarsınız. Yalnızca ele almaya hazır olduğunuz istisnaları yakalamak çok daha zariftir.

İşte Python 3 istisna hiyerarşisi - gerçekten hepsini yakalamak istiyor musunuz ?:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StopAsyncIteration
      +-- ArithmeticError
      |    +-- FloatingPointError
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      +-- AssertionError
      +-- AttributeError
      +-- BufferError
      +-- EOFError
      +-- ImportError
           +-- ModuleNotFoundError
      +-- LookupError
      |    +-- IndexError
      |    +-- KeyError
      +-- MemoryError
      +-- NameError
      |    +-- UnboundLocalError
      +-- OSError
      |    +-- BlockingIOError
      |    +-- ChildProcessError
      |    +-- ConnectionError
      |    |    +-- BrokenPipeError
      |    |    +-- ConnectionAbortedError
      |    |    +-- ConnectionRefusedError
      |    |    +-- ConnectionResetError
      |    +-- FileExistsError
      |    +-- FileNotFoundError
      |    +-- InterruptedError
      |    +-- IsADirectoryError
      |    +-- NotADirectoryError
      |    +-- PermissionError
      |    +-- ProcessLookupError
      |    +-- TimeoutError
      +-- ReferenceError
      +-- RuntimeError
      |    +-- NotImplementedError
      |    +-- RecursionError
      +-- SyntaxError
      |    +-- IndentationError
      |         +-- TabError
      +-- SystemError
      +-- TypeError
      +-- ValueError
      |    +-- UnicodeError
      |         +-- UnicodeDecodeError
      |         +-- UnicodeEncodeError
      |         +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
           +-- ImportWarning
           +-- UnicodeWarning
           +-- BytesWarning
           +-- ResourceWarning

Bunu yapma

Bu istisna işleme biçimini kullanıyorsanız:

try:
    something
except: # don't just do a bare except!
    pass

O zaman somethingbloğunuzu Ctrl-C ile kesemezsiniz. Programınız, trykod bloğundaki olası tüm İstisnaları göz ardı edecektir .

İşte aynı istenmeyen davranışa sahip olacak başka bir örnek:

except BaseException as e: # don't do this either - same as bare!
    logging.info(e)

Bunun yerine, yalnızca aradığınızı bildiğiniz özel durumu yakalamaya çalışın. Örneğin, bir dönüşümde değer hatası alabileceğinizi biliyorsanız:

try:
    foo = operation_that_includes_int(foo)
except ValueError as e:
    if fatal_condition(): # You can raise the exception if it's bad,
        logging.info(e)   # but if it's fatal every time,
        raise             # you probably should just not catch it.
    else:                 # Only catch exceptions you are prepared to handle.
        foo = 0           # Here we simply assign foo to 0 and continue. 

Başka bir örnekle daha fazla açıklama

Bunu web kazıma yaptığınızdan ve a diyorsunuz olabilir, UnicodeErrorancak en geniş İstisna yakalama yöntemini kullandığınız için, diğer temel kusurlara sahip olabilen kodunuz tamamlanmaya çalışacak, bant genişliği harcanmaya çalışacak , işlem süresi, ekipmanınızın aşınması ve yıpranması, belleğin bitmesi, çöp verilerinin toplanması vb.

Diğer insanlar kodunuza güvenebilmeniz için sizden tamamlamanızı isterse, her şeyi işlemek zorunda olduğunuzu anlıyorum. Ancak, geliştikçe gürültülü bir şekilde başarısız olmak istiyorsanız, sadece aralıklı olarak ortaya çıkabilecek sorunları düzeltme fırsatına sahip olacaksınız, ancak bu uzun vadeli maliyetli hatalar olacaktır.

Daha kesin hata yönetimi ile kod daha sağlam olabilir.


31
>>> import this

Python'un Zen'i, Tim Peters

Güzel, çirkin olmaktan iyidir.
Açık, örtük olmaktan iyidir.
Basit, karmaşık olmaktan iyidir.
Karmaşık karmaşık olmaktan iyidir.
Düz iç içe geçmişten daha iyidir.
Seyrek yoğun olmaktan iyidir.
Okunabilirlik önemlidir.
Özel durumlar kuralları ihlal edecek kadar özel değildir.
Pratiklik saflığı yenmesine rağmen.
Hatalar asla sessizce geçmemelidir.
Açıkça susturulmadıkça.
Belirsizlik karşısında, tahmin etme isteğini reddet.
Bunu yapmanın tek ve tercihen tek bir yolu olmalı.
Her ne kadar Hollandalı değilseniz bu yol ilk başta belli olmayabilir.
Şimdi hiç olmadığı kadar iyi.
Her ne kadar asla genellikle daha iyi olmasa daSağ şimdi.
Uygulamanın açıklanması zorsa, bu kötü bir fikirdir.
Uygulamanın açıklanması kolaysa, iyi bir fikir olabilir.
İsim alanları harika bir fikirdir - hadi bunlardan daha fazlasını yapalım!

İşte benim görüşüm. Bir hata bulduğunuzda, onu işlemek için bir şey yapmalısınız, yani günlük dosyasına veya başka bir şeye yazın. En azından eskiden bir hata olduğunu bildirir.


64
-1 Otoriteden gelen tartışma aslında hiçbir şeyi açıklamaz . Yetki yanlış olabilir.
Izkata

23
@Izkata'nın yazdığı ve AND'ın altında bir satır, aynı otorite şöyle yazar: "Açıkça susturulmadıkça", yani tam olarak: pass yapar.
Ofri Raviv

13
@OfriRaviv Hayır, hata dolaylı olarak geçmiyor mu? Açıkça sessizce geçmesi gereken hatanın, yani bu konuda açık olmanın isimlendirilmesini gerektirir . Dışında bu değil: pass yapar.
Chelonian

24

En azından veya except Exception:gibi sistem istisnalarını yakalamaktan kaçınmalısınız . İşte dokümanlara bağlantı .SystemExitKeyboardInterrupt

Genel olarak, istenmeyen istisnaları yakalamaktan kaçınmak için, yakalamak istediğiniz istisnaları açıkça tanımlamanız gerekir. Hangi istisnaları görmezden geldiğinizi bilmelisiniz .


13

İlk olarak, Python Zen'in iki prensibini ihlal ediyor :

  • Açık, örtük olmaktan iyidir
  • Hatalar asla sessizce geçmemelidir

Bunun anlamı, kasten hatanızın sessizce geçmesini sağlamanızdır. Ayrıca, hangi hatanın tam olarak meydana geldiğini bilmiyorsunuz, çünkü except: passherhangi bir istisna yakalayacak.

Biz Python Zen'den soyut koyma deneyin ve sadece aklı vadede konuşmak, ikinci olarak, kullandığınız olduğunu bilmeli except:passile yaprakları size hiçbir bilgi ve kontrol sisteminizde. Temel kural, hata oluşursa bir istisna oluşturmak ve uygun işlemleri yapmaktır. Önceden bilmiyorsanız, bunların hangi eylemler olması gerektiğini, en azından hatayı bir yere kaydedin (ve istisnayı yeniden yükseltin):

try:
    something
except:
    logger.exception('Something happened')

Ancak, genellikle, herhangi bir istisna yakalamaya çalışırsanız, muhtemelen yanlış bir şey yapıyorsunuzdur!


2
... açıkça susturulmadıkça, OP'de durum böyle.
Hyperboreus

Çözümünüzü bilmek istiyorum. Aslında, gerçekten hiçbir şeyin yapılması gerekmediğinde, sadece hataları listeler ve yorum yapar ve günlükleri yazarım. Sonra sadece geç.
Booster

2
@Hyperboreus, sanmıyorum, tüm ve herhangi bir hatayı yakalamak onları açıkça susturuyor, yani, ne yakaladığını bile bilmiyorsun.
Alexander Zhukov

13
"Çünkü bir adam böyle söylüyor" gerçekten "Neden?" soru.
Sebastian Negraszus

12

except:passYapı esasen kod kaplı iken gelip her türlü istisnai durumları sustururtry: blokta çalıştırılıyor.

Bu kötü uygulamayı yapan şey, aslında gerçekten istediğiniz şey olmamasıdır. Daha sık, susturmak istediğiniz belirli bir durum ortaya çıkar ve except:passçok künt bir enstrümandır. İşi yapacak, ancak muhtemelen tahmin etmediğiniz diğer hata koşullarını da maskeleyecek, ancak başka bir şekilde ele almak isteyebilir.

Bunu Python'da özellikle önemli kılan şey, bu dilin deyimleriyle, istisnaların mutlaka hata olmamasıdır . Çoğu dilde olduğu gibi, genellikle bu şekilde kullanılırlar. Ancak özellikle Python, bazen normal çalışan durumun bir parçası olmayan, ancak zaman zaman geldiği ve hatta çoğu durumda beklenebileceği bilinen bazı kod görevlerinden alternatif bir çıkış yolu uygulamak için bunları kullandı. SystemExitzaten eski bir örnek olarak bahsedilmiş, ancak günümüzde en yaygın örnek olabilir StopIteration. İstisnaları bu şekilde kullanmak, özellikle yineleyiciler ve jeneratörler Python'a ilk kez tanıtıldığında çok fazla tartışmaya neden oldu, ancak sonunda fikir galip geldi.


12

# 1 nedeni zaten belirtildi - beklemediğiniz hataları gizler.

(# 2) - Kodunuzun başkalarının okumasını ve anlamasını zorlaştırır. Bir dosyayı okumaya çalışırken bir FileNotFoundException yakalarsanız, başka bir geliştirici için 'catch' bloğunun hangi işlevselliğe sahip olması gerektiği açıktır. Bir istisna belirtmezseniz, bloğun ne yapması gerektiğini açıklamak için ek yorum yapmanız gerekir.

(# 3) - Tembel programlamayı gösterir. Genel try / catch kullanırsanız, programınızdaki olası çalışma zamanı hatalarını anlamadığınızı veya Python'da hangi istisnaların mümkün olduğunu bilmediğiniz anlamına gelir. Belirli bir hatayı yakalamak, hem programınızı hem de Python'un attığı hata aralığını anladığınızı gösterir. Bu, diğer geliştiricilerin ve kod gözden geçirenlerin çalışmanıza güvenme olasılığını artırır.


12

Peki, bu kod hangi çıktıyı üretir?

fruits = [ 'apple', 'pear', 'carrot', 'banana' ]

found = False
try:
     for i in range(len(fruit)):
         if fruits[i] == 'apple':
             found = true
except:
     pass

if found:
    print "Found an apple"
else:
    print "No apples in list"

Şimdi try- exceptbloğunun karmaşık bir nesne hiyerarşisine yapılan yüzlerce çağrı hattı olduğunu ve büyük programın çağrı ağacının ortasında çağrıldığını hayal edin . Program yanlış gittiğinde nereye bakmaya başlıyorsunuz?


5
Er, bunu 'düzelten' millet sayesinde, ama lütfen yapma - 'röportaj sorusu' anlamında kasıtlı olarak yanlış. Muhtemelen ilk ortaya çıkması daha incedir - deneyin. Demek istediğim, özellikle Python'da 'tüm' istisnaları ezmek, önemsiz bir düzine kod satırında bile hata ayıklamayı zorlaştırıyor.
Ian Harvey

11

Genel olarak, herhangi bir hatayı / istisnayı üç kategoriden birinde sınıflandırabilirsiniz :

  • Ölümcül : Senin hatan değil, onları engelleyemezsin, onlardan kurtaramazsın. Kesinlikle onları görmezden gelmemeli ve devam etmeli ve programınızı bilinmeyen bir durumda bırakmamalısınız. Hatanın programınızı sonlandırmasına izin verin, yapabileceğiniz hiçbir şey yok.

  • Boneheaded : Büyük olasılıkla bir gözetim, hata veya programlama hatası nedeniyle kendi hatanız . Hatayı düzeltmelisiniz. Yine, kesinlikle görmezden gelmemeli ve devam etmemelisiniz.

  • Ekzojen : Dosya bulunamadı veya bağlantı sonlandırıldı gibi istisnai durumlarda bu hataları bekleyebilirsiniz . Bu hataları ve yalnızca bunları açıkça kullanmalısınız.

Her durumda except: pass, programınızı yalnızca daha fazla hasara neden olabileceği bilinmeyen bir durumda bırakacaktır.


6

Basitçe söylemek gerekirse, bir istisna veya hata atılırsa, bir şeyler yanlıştır. Çok yanlış bir şey olmayabilir, ancak sadece goto ifadelerini kullanmak uğruna hatalar ve istisnalar oluşturmak, atmak ve yakalamak iyi bir fikir değildir ve nadiren yapılır. Zamanın% 99'unda bir yerde bir sorun vardı.

Sorunlar çözülmeli. Tıpkı yaşamda, programlamada olduğu gibi, problemleri yalnız bırakırsanız ve görmezden gelmeye çalışırsanız, sadece kendi başlarına gitmezler; bunun yerine büyür ve çoğalırlar. Bir sorunun üzerinizde büyümesini ve yolun aşağısında tekrar çarpmasını önlemek için, ya 1) ortadan kaldırırsınız ve daha sonra karışıklığı temizlersiniz veya 2) sorunu içerir ve daha sonra karışıklığı temizlersiniz.

İstisnaları ve hataları görmezden gelmek ve bu şekilde bırakmak, bellek sızıntılarını, olağanüstü veritabanı bağlantılarını, dosya izinlerinde gereksiz kilitleri vb.

Nadir durumlarda, sorun o kadar küçük, önemsiz ve - bir denemeye ihtiyaç duymanın yanı sıra ... catch bloğu - kendine yeten , daha sonra temizlenecek hiçbir karışıklık yok. Bu en iyi uygulamanın mutlaka geçerli olmadığı tek durumlar bunlar. Deneyimlerime göre, bu genellikle kodun yaptığı her şeyin temelde küçük ve affedilebilir olduğu anlamına gelir ve yeniden deneme girişimleri veya özel mesajlar gibi bir şey ne karmaşıklığa ne de ipliği tutmaya değmez.

Benim şirkette, kural hemen hemen her zaman yapmaktır şey bir catch bloğunda ve bir şey yapmazsak, o zaman her zaman çok iyi bir neden ile bir yorum neden olmasın yerleştirmelidir. Yapılacak bir şey olduğunda asla boş bir yakalama bloğunu geçmemeli veya bırakmamalısınız.


6

Bence hataların görünmesi için bir nedenim var, sesim aptal, ama bu böyle. İyi programlama hataları ancak bunları ele almanız gerektiğinde yükseltir. Ayrıca, bir süre önce okuduğum gibi, "pass-Statement, daha sonra eklenecek Shows kodunu gösteren bir Deyimdir", bu nedenle boş bir ifade deyimi kullanmaktan çekinmeyin, ancak iyi bir program için bir parçası olmak. çünkü sahip olmanız gereken şeylerle başa çıkmıyorsunuz. Görünen istisnalar, giriş verilerini düzeltme veya veri yapınızı değiştirme şansı verir, böylece bu istisnalar tekrar ortaya çıkmaz (ancak çoğu durumda (Ağ istisnaları, Genel girdi istisnaları) istisnalar, programın sonraki bölümlerinin iyi çalışmadığını gösterir. Örneğin, NetworkException bozuk bir ağ bağlantısını gösterebilir ve program sonraki program adımlarında veri gönderemez / alamaz.

Ancak, yalnızca bir yürütme bloğu için bir geçiş bloğu kullanmak geçerlidir, çünkü istisna türleri arasında hala farklılaşırsınız, bu nedenle tüm istisna bloklarını birine koyarsanız, boş değildir:

try:
    #code here
except Error1:
    #exception handle1

except Error2:
    #exception handle2
#and so on

şu şekilde yeniden yazılabilir:

try:
    #code here
except BaseException as e:
    if isinstance(e, Error1):
        #exception handle1

    elif isinstance(e, Error2):
        #exception handle2

    ...

    else:
        raise

Bu nedenle, pass-ifadeleri olan çoklu bloklar bile, yapısı özel istisna türlerini işleyen kodlarla sonuçlanabilir.


4

Şimdiye kadar yapılan tüm yorumlar geçerlidir. Mümkün olduğunda, tam olarak hangi istisnayı yoksaymak istediğinizi belirtmeniz gerekir. Mümkün olduğunda, istisnanın nedenini analiz etmeniz ve geri kalanı değil, yalnızca görmezden gelmek istediğiniz şeyi göz ardı etmeniz gerekir. İstisna, uygulamanın "muhteşem bir şekilde çökmesine" neden olursa, sorun o zaman meydana geldiğini gizlemekten çok, gerçekleştiğinde beklenmedik olayları bilmek çok daha önemlidir.

Tüm bunlarla birlikte, herhangi bir programlama uygulamasını en önemli şey olarak kabul etmeyin. Bu aptalca. Her zaman istisnaları yoksay blokunun yapılması için zaman ve yer vardır.

Idiotic en önemli örneklerden biri de gotooperatörün kullanılmasıdır. Okuldayken, profesörümüz bize gotosadece onu kullanmayacağınızı söylememizi öğretti . İnsanların size xyz'in asla kullanılmaması gerektiğini ve yararlı olduğunda bir senaryo olamayacağını söyleyenlere inanmayın. Her zaman vardır.


1
"Git" davası stilistik ve bir fikir meselesidir, oysa "hariç: geçiş" genellikle yanlıştır. Birisi, örneğin, o noktada sürecinizi "-TERM" öldürecekse, bunu görmezden gelmesi gerektiğini varsayar. En azından bu kötü davranış.
Score_Under

1
@Score_Under bunun uygun olduğu durumlar var. Örneğin, aradığınız bir işlev, kaynağı / yazarı bilinmeyen bir tamamlayıcı olduğunda, temel işlevselliği etkilemez, ancak çökmeler sorun yaratabilirse. Bu tür çağrıların doğru bir şekilde araştırılması ve analiz edilmesi gerektiğini iddia edeceğinizi biliyorum, ancak gerçek hayatta her zaman mümkün değildir.
galets

Yine de, eğer sürecinizi sonlandırmak istersem, öldürmek -9 tek güvenilir seçenek olmamalıdır.
Score_Under

2

Hataları ele almak programlamada çok önemlidir. Neyin yanlış gittiğini kullanıcıya göstermeniz gerekir. Çok az durumda hataları göz ardı edebilirsiniz. Bu çok kötü bir programlama uygulaması.


2

Henüz bahsedilmediğinden, kullanımı daha iyi bir stil contextlib.suppress:

with suppress(FileNotFoundError):
    os.remove('somefile.tmp')

Sağlanan örnekte , istisna olsa da olmasa da program durumunun aynı kaldığına dikkat edin. Yani somefile.tmpher zaman var olmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.