İstisnalar nasıl düzgün şekilde yoksayılır?


777

İstisnayı ele almadan bir deneme-dışında yapmak istediğinizde, bunu Python'da nasıl yaparsınız?

Aşağıdakiler bunu yapmanın doğru yolu mu?

try:
    shutil.rmtree(path)
except:
    pass

10
Şimdiye kadar kimsenin bundan bahsetmediği garip (cevabımda yaptım), ancak bu özel işlev için sadece yapabilirsiniz shutil.rmtree(path, ignore_errors=True). Ancak bu çoğu işlev için geçerli değildir.
Aaron Hall

9
İstisnaları göz ardı etmeyi düşünürken önemli okuma: ““: pass ”neden kötü bir programlama uygulamasıdır?
dürtmek

3
Bunu gerçek hayatta yaptığınızı düşünün. deneyin: get_cash ('$ 1000') hariç: # meh, muhtemelen iyi olacak
Grokodile

Gerçek hayat:try: rob() except: run()
PatrickT

Yanıtlar:


1039
try:
    doSomething()
except: 
    pass

veya

try:
    doSomething()
except Exception: 
    pass

Fark İlki da yakalayacak olması KeyboardInterrupt, SystemExitve doğrudan elde böyle şeyler, exceptions.BaseExceptiondeğil, exceptions.Exception.

Ayrıntılar için belgelere bakın:


4
StopIteration ve Warning öğelerinin de Exception öğesinden miras aldığını unutmayın. İhtiyaçlarınıza bağlı olarak bunun yerine StandardError'dan miras almak isteyebilirsiniz.
Ben Blank

1
Bu doğrudur, ancak dikkatli değilseniz ince hatalarla karşılaşabilirsiniz (özellikle StopIteration'ı geçmek dışında bir şey yapıyorsanız).
Jason Baker

17
-1, try: shuti.rmtree(...) except: passherhangi bir hatayı kabaca bastırır ( shutilsonuçta yanlış yazmış olsanız bile NameError) - en azındanexcept OSError:
dbr

44
Bu cevap, bilgilendirici olsa da, önemli bir bilgiyi kaçırmaktadır - asla bu şekilde bir istisna yakalamamalısınız. Bunun yerine, her zaman sadece önem verdiğiniz istisnaları yakalamaya çalışmalısınız, aksi takdirde jenerik "hariç" ler tarafından gizlenen önemsiz böcekleri avlarken kabuslarınız olacaktır. Daha fazla bilgi için dbr'nin cevabına bakınız. (Bunun orijinal soru olmadığını biliyorum - ama bunu arayan herkes sadece snippet'inizi alacak ve olduğu gibi kullanacak)
johndodo

139

Genellikle ilgilendiğiniz hataları yakalamak sadece en iyi uygulama olarak kabul hâlinde. shutil.rmtreeBunun muhtemelen OSError:

>>> shutil.rmtree("/fake/dir")
Traceback (most recent call last):
    [...]
OSError: [Errno 2] No such file or directory: '/fake/dir'

Bu hatayı sessizce yoksaymak isterseniz şunları yaparsınız:

try:
    shutil.rmtree(path)
except OSError:
    pass

Neden? Diyelim ki (bir şekilde) yanlışlıkla bir dize yerine bir tamsayı iletin, örneğin:

shutil.rmtree(2)

"TypeError: Unicode'a zorlama: dize veya arabellek gerekir, int bulundu" hatasını verir - muhtemelen bunu göz ardı etmek istemezsiniz, bu hata ayıklamak zor olabilir.

Eğer varsa kesinlikle tüm hataları görmezden istiyorum yakalamak Exceptionçıplak ziyade except:açıklamada. Yine neden?

Bir istisna belirtmemek , örneğin aşağıdakileri kullanan istisna da dahil olmak üzere her istisnayı yakalar :SystemExitsys.exit()

>>> try:
...     sys.exit(1)
... except:
...     pass
... 
>>>

Bunu, doğru şekilde çıkan aşağıdakilerle karşılaştırın:

>>> try:
...     sys.exit(1)
... except Exception:
...     pass
... 
shell:~$ 

Daha iyi davranış kodu yazmak istiyorsanız, OSErroristisna çeşitli hataları temsil edebilir, ancak yukarıdaki örnekte yalnızca yok saymak istiyoruz Errno 2, bu yüzden daha da spesifik olabiliriz:

import errno

try:
    shutil.rmtree(path)
except OSError as e:
    if e.errno != errno.ENOENT:
        # ignore "No such file or directory", but re-raise other errors
        raise

1
shutil.rmtreeen iyi örnek değil, çünkü sadece ignore_errors=Truebu işlev için kullanabilirsiniz ..
wim

113

İstisnayı ele almadan bir deneme yakalaması yapmak istediğinizde, bunu Python'da nasıl yaparsınız?

"Elleçleme" ile ne demek istediğinize bağlıdır.

Herhangi bir işlem yapmadan yakalamak istiyorsanız, postaladığınız kod çalışacaktır.

İstisnanın yığına çıkmasını engellemeden bir istisna üzerinde işlem yapmak istediğinizi kastediyorsanız, şöyle bir şey istersiniz:

try:
    do_something()
except:
    handle_exception()
    raise  #re-raise the exact same exception that was thrown

88

Öncelikle Jack o'Connor'ın bu konudaki cevabını alıntıladım . Burada yazılan başvurulan konu kapatıldı:

"Python 3.4'te bunu yapmanın yeni bir yolu var:

from contextlib import suppress

with suppress(Exception):
    # your code

İşte ekleyen taahhüt: http://hg.python.org/cpython/rev/406b47c64480

Ve işte yazar Raymond Hettinger, bu ve diğer her türlü Python sıcaklığından bahsediyor: https://youtu.be/OSGv2VnC0go?t=43m23s

Buna ek olarak Python 2.7 eşdeğeri:

from contextlib import contextmanager

@contextmanager
def ignored(*exceptions):
    try:
        yield
    except exceptions:
        pass

Sonra Python 3.4 gibi kullanın:

with ignored(Exception):
    # your code

55

Tamamlamak için:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print("division by zero!")
...     else:
...         print("result is", result)
...     finally:
...         print("executing finally clause")

Ayrıca, istisnayı şöyle yakalayabileceğinizi unutmayın:

>>> try:
...     this_fails()
... except ZeroDivisionError as err:
...     print("Handling run-time error:", err)

... ve istisnayı şu şekilde yeniden yükseltin:

>>> try:
...     raise NameError('HiThere')
... except NameError:
...     print('An exception flew by!')
...     raise

... python öğreticisinden örnekler .


43

İstisnalar nasıl düzgün şekilde göz ardı edilir?

Bunu yapmanın çeşitli yolları var.

Bununla birlikte, örnek seçiminin genel durumu kapsayan basit bir çözümü vardır.

Örneğe özgü:

Onun yerine

try:
    shutil.rmtree(path)
except:
    pass

Bunu yap:

shutil.rmtree(path, ignore_errors=True)

Bu özel bir argüman shutil.rmtree. Aşağıdakileri yaparak bununla ilgili yardımı görebilirsiniz ve bunun da hatalarda işlevselliğe izin verebileceğini göreceksiniz.

>>> import shutil
>>> help(shutil.rmtree)

Bu yalnızca örneğin dar durumunu kapsadığından, bu anahtar kelime bağımsız değişkenleri yoksa bunun nasıl ele alınacağını daha fazla göstereceğim.

Genel yaklaşım

Yukarıdakiler yalnızca örneğin dar durumunu kapsadığından, bu anahtar kelime bağımsız değişkenleri yoksa bunun nasıl ele alınacağını daha fazla göstereceğim.

Python 3.4'teki yenilikler:

suppressİçerik yöneticisini içe aktarabilirsiniz :

from contextlib import suppress

Ancak yalnızca en özel istisnayı bastırın:

with suppress(FileNotFoundError):
    shutil.rmtree(path)

Sessizce bir FileNotFoundError:

>>> with suppress(FileNotFoundError):
...     shutil.rmtree('bajkjbkdlsjfljsf')
... 
>>> 

Gönderen docs :

İstisnaları tamamen bastıran diğer mekanizmalarda olduğu gibi, bu bağlam yöneticisi yalnızca program yürütmeye sessizce devam etmenin yapılması gereken doğru şey olduğu bilinen çok spesifik hataları kapsamak için kullanılmalıdır.

suppressVe FileNotFoundErroryalnızca Python 3'te kullanılabilir olduğunu unutmayın .

Kodunuzun Python 2'de de çalışmasını istiyorsanız, bir sonraki bölüme bakın:

Python 2 ve 3:

İstisnayı kullanmadan bir deneme / hariç yapmak istediğinizde, Python'da nasıl yaparsınız?

Aşağıdakiler bunu yapmanın doğru yolu mu?

try :
    shutil.rmtree ( path )
except :
    pass

Python 2 uyumlu kod için, passno-op olmayan bir ifadeye sahip olmanın doğru yoludur. Bir çıplak yaptığınızda Fakat except:, bunu yaparken aynı şey except BaseException:içeren GeneratorExit, KeyboardInterruptve SystemExit, ve genel olarak, o şeyleri yakalamak istemiyorum.

Aslında, istisnayı olabildiğince isimlendirirken spesifik olmalısınız.

İşte Python (2) istisna hiyerarşisinin bir parçası ve gördüğünüz gibi, daha genel İstisnalar yakalarsanız, beklemediğiniz sorunları gizleyebilirsiniz:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
... and so on

Muhtemelen burada bir OSError yakalamak istersiniz ve belki de umursamadığınız istisna dizin yoksa.

Biz alabilirsiniz o özel hata numarayı errnobunu yoksa kütüphane ve tekrar yükseltti:

import errno

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno == errno.ENOENT: # no such file or directory
        pass
    else: # we had an OSError we didn't expect, so reraise it
        raise 

Unutmayın, çıplak bir yükseltme orijinal istisnayı yükseltir, bu muhtemelen bu durumda istediğiniz şeydir. passİstisna işlemede açıkça kodla ihtiyacımız olmadığı için daha kısaca yazılmıştır :

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno != errno.ENOENT: # no such file or directory
        raise 

11

İstisnayı ele almadan bir deneme yakalaması yapmak istediğinizde, bunu Python'da nasıl yaparsınız?

Bu, istisnanın ne olduğunu yazdırmanıza yardımcı olacaktır :( yani istisnayı ele almadan yakalamayı deneyin ve istisnayı yazdırın.)

import sys
try:
    doSomething()
except:
    print "Unexpected error:", sys.exc_info()[0]

10
try:
      doSomething()
except Exception: 
    pass
else:
      stuffDoneIf()
      TryClauseSucceeds()

FYI else yan tümcesi tüm istisnalardan sonra gidebilir ve yalnızca denemedeki kod bir istisnaya neden olmazsa çalıştırılır.


1
Son olarak elsebu bağlamda iyi bir açıklama . Ve eklemek için finallyher zaman herhangi bir (veya istisna) sonra çalışır.
not2qubit

5

Birden fazla komuttaki hataları görmezden gelmem gerekiyordu ve fuckit hile yaptı

import fuckit

@fuckit
def helper():
    print('before')
    1/0
    print('after1')
    1/0
    print('after2')

helper()

+1 çünkü kesinlikle benim günümü yaptın çünkü bu kaynak kod içinde canlı yığını değiştirmek gibi son derece faydalı şeyler öğrenebilirsin
WBAR

3

Python'da, diğer dile benzer istisnaları ele alıyoruz, ancak fark bazı sözdizimi farkıdır, örneğin,

try:
    #Your code in which exception can occur
except <here we can put in a particular exception name>:
    # We can call that exception here also, like ZeroDivisionError()
    # now your code
# We can put in a finally block also
finally:
    # Your code...

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.