Soulever (lancer) manuellement une exception en Python

Comment puis-je soulever une exception en Python pour qu'elle puisse plus tard être attrapée via un bloc except ?

1607
demandé sur DavidRR 2010-01-13 00:07:40

5 réponses

comment lancer/soulever manuellement une exception en Python?

utilisez le constructeur D'Exception le plus spécifique qui s'adapte sémantiquement à votre numéro .

soyez précis dans votre message, par exemple:

raise ValueError('A very specific bad thing happened.')

Ne pas soulever des exceptions génériques

éviter d'invoquer une Exception Générique. Pour l'attraper, vous devez prendre toutes les autres plus exceptions spécifiques qui le sous-tendent.

Problème 1: Cacher les bogues

raise Exception('I know Python!') # Don't! If you catch, likely to hide bugs.

par exemple:

def demo_bad_catch():
    try:
        raise ValueError('Represents a hidden bug, do not catch this')
        raise Exception('This is the exception you expect to handle')
    except Exception as error:
        print('Caught this error: ' + repr(error))

>>> demo_bad_catch()
Caught this error: ValueError('Represents a hidden bug, do not catch this',)

Problème 2: ne prends pas

et les prises plus spécifiques ne seront pas l'exception générale:

def demo_no_catch():
    try:
        raise Exception('general exceptions not caught by specific handling')
    except ValueError as e:
        print('we will not catch exception: Exception')


>>> demo_no_catch()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in demo_no_catch
Exception: general exceptions not caught by specific handling

Meilleures Pratiques: raise déclaration

à la place, utilisez le constructeur D'Exception le plus spécifique qui sémantiquement adapté à votre numéro .

raise ValueError('A very specific bad thing happened')

qui permet aussi de passer un nombre arbitraire d'arguments au constructeur:

raise ValueError('A very specific bad thing happened', 'foo', 'bar', 'baz') 

ces arguments sont accessibles par l'attribut args sur l'objet Exception. Par exemple:

try:
    some_code_that_may_raise_our_value_error()
except ValueError as err:
    print(err.args)

imprime

('message', 'foo', 'bar', 'baz')    

en python 2.5, un attribut message a été ajouté à BaseException en l'introduction de message et la dévalorisation originale de l'args a été rétractée .

meilleures pratiques: except clause

Lorsqu'à l'intérieur d'une clause d'Exception, vous voudrez peut-être, par exemple, enregistrer qu'un type spécifique d'erreur s'est produit, puis relancer. La meilleure façon de le faire tout en conservant la trace de la pile est d'utiliser un déclaration d'augmentation nue. Par exemple:

logger = logging.getLogger(__name__)

try:
    do_something_in_app_that_breaks_easily()
except AppError as error:
    logger.error(error)
    raise                 # just this!
    # raise AppError      # Don't do this, you'll lose the stack trace!

Ne modifiez pas vos erreurs... mais si vous insistez.

vous pouvez conserver le stacktrace (et la valeur d'erreur) avec sys.exc_info() , mais c'est beaucoup plus sujet aux erreurs et a des problèmes de compatibilité entre Python 2 et 3 , préfèrent utiliser un nu raise pour relancer.

pour expliquer - le sys.exc_info() renvoie le type, valeur, et de retraçage.

type, value, traceback = sys.exc_info()

c'est la syntaxe en Python 2 - notez que ce n'est pas compatible avec Python 3:

    raise AppError, error, sys.exc_info()[2] # avoid this.
    # Equivalently, as error *is* the second object:
    raise sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]

si vous le souhaitez, vous pouvez modifier ce qui se passe avec votre nouvelle relance-par exemple, définir new args pour l'instance:

def error():
    raise ValueError('oops!')

def catch_error_modify_message():
    try:
        error()
    except ValueError:
        error_type, error_instance, traceback = sys.exc_info()
        error_instance.args = (error_instance.args[0] + ' <modification>',)
        raise error_type, error_instance, traceback

et nous avons conservé tout le traceback tout en modifiant l'args. Notez que ceci est pas une pratique exemplaire et il est syntaxe invalide en Python 3 (rendant la conservation de la compatibilité beaucoup plus difficile à contourner).

>>> catch_error_modify_message()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in catch_error_modify_message
  File "<stdin>", line 2, in error
ValueError: oops! <modification>

In Python 3 :

    raise error.with_traceback(sys.exc_info()[2])

encore une fois: éviter de manipuler manuellement les tracebacks. C'est moins efficace et plus sujet aux erreurs. Et si vous utilisez threading et sys.exc_info vous pouvez même obtenir le mauvais traceback (surtout si vous utilisez la manipulation d'exception pour le flux de contrôle - j'aurais personnellement tendance à l'éviter.)

Python 3, à l'Exception de chaînage

en Python 3, Vous pouvez chain Exceptions, qui préservent tracebacks:

    raise RuntimeError('specific message') from error

attention:

  • ce ne permettent de changer le type d'erreur soulevée, et
  • c'est pas compatible avec Python 2.

Méthodes Dépréciées:

ceux-ci peuvent facilement se cacher et même entrer dans le code de production. Vous voulez soulever une exception, et le faire soulèvera une exception, mais pas celle prévue!

valide en Python 2, mais pas en Python 3 est le suivant:

raise ValueError, 'message' # Don't do this, it's deprecated!

Seulement valable dans beaucoup d'anciennes versions de Python (2.4 et plus bas), vous pouvez encore voir des gens lever des cordes:

raise 'message' # really really wrong. don't do this.

dans toutes les versions modernes, cela soulèvera en fait une erreur de typographie, parce que vous n'élevez pas un type BaseException. Si vous ne Vérifiez pas la bonne exception et n'avez pas un examinateur qui est au courant du problème, il pourrait entrer en production.

Exemple D'Usage

J'augmente les Exceptions pour avertir les consommateurs de mon API s'ils l'utilisent incorrectement:

def api_func(foo):
    '''foo should be either 'baz' or 'bar'. returns something very useful.'''
    if foo not in _ALLOWED_ARGS:
        raise ValueError('{foo} wrong, use "baz" or "bar"'.format(foo=repr(foo)))

Créez vos propres types d'erreur quand apropos

"je veux faire une erreur sur le but, que ce serait aller dans le" sauf

vous pouvez créer vos propres types d'erreurs, si vous voulez indiquer quelque chose de spécifique est faux avec votre application, juste sous-classe le point approprié dans la hiérarchie d'exception:

class MyAppLookupError(LookupError):
    '''raise this when there's a lookup error for my app'''

et d'utilisation:

if important_key not in resource_dict and not ok_to_be_missing:
    raise MyAppLookupError('resource is missing, and that is not ok.')
2012
répondu Aaron Hall 2017-10-28 20:07:54

NE FAITES PAS ÇA . Soulever un nu Exception est absolument pas la bonne chose à faire; voir excellente réponse D'Aaron Hall à la place.

ne Peut pas obtenir beaucoup plus pythonic que cela:

raise Exception("I know python!")

Voir l'instruction raise docs pour python si vous souhaitez plus d'info.

536
répondu Gabriel Hurley 2017-05-23 10:31:39

pour le cas commun où vous avez besoin de jeter une exception en réponse à certaines conditions inattendues, et que vous n'avez jamais l'intention d'attraper, mais tout simplement pour échouer rapidement pour vous permettre de déboguer de là si elle se produit jamais - le plus logique semble être AssertionError :

if 0 < distance <= RADIUS:
    #Do something.
elif RADIUS < distance:
    #Do something.
else:
    raise AssertionError("Unexpected value of 'distance'!", distance)
30
répondu Evgeni Sergeev 2015-05-19 04:55:14

en Python3 il y a 4 syntaxes différentes pour les exceptions de rasage:

1. raise exception 
2. raise exception (args) 
3. raise
4. raise exception (args) from original_exception

1. raise exception vs 2. raise exception (args)

si vous utilisez raise exception (args) pour soulever une exception, alors le args sera imprimé lorsque vous imprimez l'objet exception - comme indiqué dans l'exemple ci-dessous.

  #raise exception (args)
    try:
        raise ValueError("I have raised an Exception")
    except ValueError as exp:
        print ("Error", exp)     # Output -> Error I have raised an Exception 



  #raise execption 
    try:
        raise ValueError
    except ValueError as exp:
        print ("Error", exp)     # Output -> Error 

3.raise

raise déclaration sans aucun argument soulève à nouveau la dernière exception. Ceci est utile si vous devez effectuer certaines actions après avoir saisi l'exception et que vous voulez ensuite la relancer. Mais s'il n'y avait pas d'exception auparavant, l'énoncé raise soulève L'Exception TypeError .

def somefunction():
    print("some cleaning")

a=10
b=0 
result=None

try:
    result=a/b
    print(result)

except Exception:            #Output ->
    somefunction()           #some cleaning
    raise                    #Traceback (most recent call last):
                             #File "python", line 8, in <module>
                             #ZeroDivisionError: division by zero

4. relever l'exception (args) de l'exception original_exception

cet énoncé est utilisé pour créer un chaînage d'exceptions dans lequel une exception soulevée en réponse à une autre exception peut contenir les détails de l'exception originale - comme indiqué dans l'exemple ci-dessous.

class MyCustomException(Exception):
pass

a=10
b=0 
reuslt=None
try:
    try:
        result=a/b

    except ZeroDivisionError as exp:
        print("ZeroDivisionError -- ",exp)
        raise MyCustomException("Zero Division ") from exp

except MyCustomException as exp:
        print("MyException",exp)
        print(exp.__cause__)

sortie:

ZeroDivisionError --  division by zero
MyException Zero Division 
division by zero
26
répondu N Randhawa 2017-07-26 10:00:38

lisez d'abord les réponses existantes, ceci n'est qu'un addendum.

notez que vous pouvez soulever des exceptions avec ou sans arguments.

exemple:

raise SystemExit

sort du programme mais vous pourriez vouloir savoir ce qui s'est passé.Donc tu peux utiliser ça.

raise SystemExit("program exited")

cela affichera" programme terminé " à stderr avant de fermer le programme.

6
répondu Anant Prakash 2017-12-02 12:59:25