HERHANGİ istisna yakalama hakkında


698

Tüm istisnaları yakalayan bir try/ exceptbloğu nasıl yazabilirim ?


4
Çoğu durumda, herhangi bir istisna yakalamaya çalışıyorsanız muhtemelen yanlış bir şey yapıyorsunuzdur. Yani kodunuzdaki bir şeyi yanlış yazabilirsiniz ve hatta bunu bile bilmezsiniz. Belirli istisnaları yakalamak iyi bir uygulamadır.
vwvolodya

12
Daha kesin olmak gerekirse, tüm olası istisnaları yakalamak yalnızca sessizce yakalanırlarsa bir sorundur. Yakalanan hata mesajlarının yazdırıldığı sys.stderrve kaydedilebileceği durumlar dışında bu yaklaşımın başka nerede uygun olduğunu düşünmek zordur . Bu tamamen geçerli ve yaygın bir istisnadır.
Evgeni Sergeev

denedin try: whatever() except Exception as e: exp_capture() mi?
Charlie Parker

Yanıtlar:


564

Yapabilirsin ama muhtemelen yapmamalısın:

try:
    do_something()
except:
    print "Caught it!"

Ancak, bu da istisnaları yakalar KeyboardInterruptve genellikle bunu istemezsiniz, değil mi? İstisnayı hemen yeniden yükseltmedikçe , dokümanlardaki aşağıdaki örneğe bakın :

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as (errno, strerror):
    print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
    print "Could not convert data to an integer."
except:
    print "Unexpected error:", sys.exc_info()[0]
    raise


15
Son except Exception:ifadeniz doğru değil, açıkça BaseException olanları yakalamak dışında çıplak söylemek gerekir .
Pykler

7
Gerçekten stderr yazdırabilirsiniz.
nyuszika7h

41
Bu ifadeye çok katılmıyorum, “olmamalı”. Bunu idareli yapmalısınız. İstisnalar ile tamamen çıldırmış ve hepsini izlemek çok acı verici bir görev olabilir ve sadece bir tanesini kaçırırsanız, üçüncü parti kütüphanelerle (bazen dinamik olarak yüklenen !!) uğraşırken zamanlar vardır. sisteminizde büyük acı böcek. Olduğu söyleniyor, mümkün olduğunca çok sayıda izlemek ve uygun şekilde işlemek ve daha sonra özledim olanlar için bir yedek yakalamak için iyidir.
Blaze

26
Garip bulduğum şey, örnek değişkenleri bildirmediğiniz bir ördek yazım dilinde, aniden tüm istisnalarınızı yazmamanızla ilgili. Hmm!
Blaze

839

Çıplak except:fıkra dışında (diğerlerinin de söylememesi gerektiği gibi) kullanmanız yeterlidir Exception:

import traceback
import logging

try:
    whatever()
except Exception as e:
    logging.error(traceback.format_exc())
    # Logs the error appropriately. 

Normalde bunu yalnızca kodunuzun en dış düzeyinde yapmayı düşünürsünüz, örneğin sonlandırılmadan önce yakalanmamış istisnaları ele almak istiyorsanız.

Avantajı except ExceptionBare üzerinde excepten Açıkçası, yakalamak alışkanlık birkaç istisna olmasıdır KeyboardInterruptve SystemExityakayı ve bu o zaman komut dosyası çıkmak için herkes için sert yapabilir yutulduğunda:.


Aklımda aynı şey vardı, ama onların bir dezavantajı olduğunu varsayalım, onların bir kez yakalandığında iki hata olduğunu varsayalım ve ve sadece baskı dışında deneyin bloğundan çıkacaksınız ve ikinci hatayı asla bilemeyeceksiniz .. .

6
Herkesin merakımın aksine, bu hala ints gibi istisnai olmayan alt sınıfları, en azından python 2.x'te yakalayacaktır.
Joseph Garvin

5
@JosephGarvin, bu yanlış, yani bu alt sınıf olmayan "istisnalar" yakalamaz Exception. intBir istisna olarak bir yükseltmenin imkansız olduğunu ve bunu yapmaya teşebbüsün , böyle bir durumda TypeErrorekteki except Exceptionmaddede yakalanacak olan bir istisna yarattığını unutmayın . Öte yandan, eski tarz bir sınıf kaldırılabilir ve alt sınıf yapan bir "non-istisna" olarak nitelendirir Exception- bu olacak çıplak tarafından yakalanmak exceptmaddesi fakat değil bir tarafından except Exceptionmaddesi.
Yoel

4
@JosephGarvin bu blog girişini kontrol edin: chris-lamb.co.uk/posts/no-one-expects-string-literal-exception Bu konuda @Yoel ile birlikteyim, testiniz sadece maskeliTypeError
Duncan

2
@CharlieParker İstediğiniz şeyse onları yakalamakta yanlış bir şey yok, ancak çoğunlukla yapmıyorsunuz. Aramak sys.exit()genellikle uygulamanın sonlandırılmasını beklediğiniz anlamına gelir, ancak SystemExit'i yakalarsanız bu uygulanmaz. Aynı şekilde, çalışan bir komut dosyasında (Windows'ta Ctrl-break) Ctrl tuşuna basarsanız, hatayı yakalamak ve devam etmemek için programın durmasını beklersiniz. Ancak, var olandan önce temizlik yapmak istiyorsanız, bunlardan birini / her ikisini de yakalayabilirsiniz.
Duncan

100

Genel istisnaları ele almak için bunu yapabilirsiniz

try:
    a = 2/0
except Exception as e:
    print e.__doc__
    print e.message

8
Tüm istisnalar için temel sınıf BaseException olduğundan ve Exception sınıf ailesinde olmayan üretim koduyla karşılaştığımdan bu durum tüm istisnaları yakalamayabilir. Bununla ilgili ayrıntılar için docs.python.org/3/library/… adresine bakın .
DDay

4
Bu, tüm istisnaları yakalamaz.
Andy_A̷n̷d̷y̷

6
Teknik olarak, sistemden çıkmayan tüm istisnaları yakalamalıdır. @DDay bağlantılı docs kaynağından: " istisna BaseException: Tüm yerleşik istisnalar için temel sınıf. Kullanıcı tanımlı sınıflar tarafından doğrudan devralınması amaçlanmaz (bunun için İstisna Kullan)." Bunu göz ardı eden bir kodla çalışmadığınız veya sistemden çıkış istisnalarını yakalamanız gerekmedikçe, yukarıdaki işlemin tamamlanması gerekir.
Peter Cassetta

@PeterCassetta ne zaman istisnalar dışında sistem yakalamak ister misiniz? Görünüşe göre bu soruları yakalamak istemiyoruz, ama nedenini anlamıyorum. Neden genellikle değil?
Charlie Parker

68

Tüm olası istisnaları yakalamak için BaseException . İstisna hiyerarşisinin en üstünde:

Python 3: https://docs.python.org/3.5/library/exceptions.html#exception-hierarchy

Python 2.7: https://docs.python.org/2.7/library/exceptions.html#exception-hierarchy

try:
    something()
except BaseException as error:
    print('An exception occurred: {}'.format(error))

Ancak diğer insanların belirttiği gibi, sadece belirli durumlar için buna ihtiyacınız olmaz.


1
Ctrl-C tuşlarına bastıktan sonra uzun süredir devam eden bir işin ilerlemesini kaydetmek istiyor musunuz?
BallpointBen

54

Burada bulunana benzer çok basit bir örnek:

http://docs.python.org/tutorial/errors.html#defining-clean-up-actions

TÜM istisnaları yakalamaya çalışıyorsanız, tüm kodunuzu "yazdır" yerine "try:" ifadesine koyun. İstisna oluşturabilecek bir işlem gerçekleştirin. ".

try:
    print "Performing an action which may throw an exception."
except Exception, error:
    print "An exception was thrown!"
    print str(error)
else:
    print "Everything looks great!"
finally:
    print "Finally is called directly after executing the try statement whether an exception is thrown or not."

Yukarıdaki örnekte, çıktıyı şu sırada görürsünüz:

1) İstisna oluşturabilecek bir işlem yapmak.

2) Son olarak, bir istisnanın atılıp atılmadığı try ifadesini uyguladıktan sonra doğrudan çağrılır.

3) "Bir istisna atıldı!" veya "Her şey harika görünüyor!" bir istisna atıp atmadığına bağlı olarak.

Bu yardımcı olur umarım!


26

Bunu özellikle Python 3.0 ve üstü ile yapmanın birçok yolu vardır

Yaklaşım 1

Bu basit bir yaklaşımdır, ancak önerilmez, çünkü hangi kod satırının istisnayı attığını tam olarak bilemezsiniz:

def bad_method():
    try:
        sqrt = 0**-1
    except Exception as e:
        print(e)

bad_method()

Yaklaşım 2

Her istisna hakkında daha fazla ayrıntı sağladığı için bu yaklaşım önerilir. O içerir:

  • Kodunuz için satır numarası
  • Dosya adı
  • Gerçek hata daha ayrıntılı bir şekilde

Tek dezavantajı geri izlemenin içe aktarılması gerektiğidir.

import traceback

def bad_method():
    try:
        sqrt = 0**-1
    except Exception:
        print(traceback.print_exc())

bad_method()

21

Python 2.7'de istisna isimleri varsa test etmek için bu küçük numarayı yeni öğrendim. Bazen i kod özel istisnalar ele var, bu yüzden bu ad işlenen istisnalar bir liste içinde olup olmadığını görmek için bir test gerekli.

try:
    raise IndexError #as test error
except Exception as e:
    excepName = type(e).__name__ # returns the name of the exception

2
try:
    whatever()
except:
    # this will catch any exception or error

Bunun uygun Python kodlaması olmadığını belirtmek gerekir. Bu, yakalamak istemeyebileceğiniz birçok hatayı da yakalar.


sadece diğer bazı yanıtlarda belirtildiği gibi tüm istisnaları önbellekleme dışında kullanın. BaseException'ı bu amaç için kullanmalısınız, ancak dediğin gibi, hiç kimse bunun gibi tüm istisnaları yakalamamalıdır. Sanırım, hedef geliştirme dışında daha ayrıntılı eklemek istiyorsanız bir başlangıç ​​için sorun değil ama sanırım ...
Pyglouthon
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.