web-dev-qa-db-fra.com

Puis-je obtenir l'exception du bloc finally en python?

J'ai une clause try/finally dans mon script. Est-il possible d'obtenir le message d'erreur exact à partir de la clause finally?

36
Goutham

Non, à finally heure sys.exc_info est tout-Aucun, qu'il y ait eu une exception ou non. Utilisation:

try:
  whatever
except:
  here sys.exc_info is valid
  to re-raise the exception, use a bare `raise`
else:
  here you know there was no exception
finally:
  and here you can do exception-independent finalization
70
Alex Martelli

Le bloc finally sera exécuté indépendamment du fait qu'une exception ait été levée ou non, donc comme le souligne Josh, vous ne voudrez probablement pas la gérer là-bas.

Si vous avez vraiment besoin de la valeur d'une exception qui a été déclenchée, vous devez intercepter l'exception dans un bloc except, la gérer correctement ou la relancer, puis utiliser cette valeur dans le bloc finally - dans l'attente qu'il ne puisse jamais avoir été fixé, si aucune exception n'a été levée lors de l'exécution.

import sys

exception_name = exception_value = None

try:
    # do stuff
except Exception, e:
    exception_name, exception_value = sys.exc_info()[:2]
    raise   # or don't -- it's up to you
finally:
    # do something with exception_name and exception_value
    # but remember that they might still be none
12
Ian Clelland

En fait, les autres réponses sont un peu vagues. Alors, permettez-moi de le clarifier. Vous pouvez toujours invoquer sys.exc_info () à partir du bloc finally. Cependant, sa sortie variera selon que l'exception a réellement été levée.

import sys

def f(i):

    try:
        if i == 1:
            raise Exception
    except Exception as e:
        print "except -> " + str(sys.exc_info())
    finally:
        print "finally -> " + str(sys.exc_info())

f(0)
f(1)

>>> 
finally -> (None, None, None)
except -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x029438F0>)
finally -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x029438F0>)

Ainsi, vous pouvez toujours savoir dans le bloc enfin, si une exception a été déclenchée, s'il s'agit d'une fonction de premier niveau. Mais sys.exc_info () se comportera différemment lorsque la longueur de la pile d'appels dépasse 1, comme illustré dans l'exemple ci-dessous. Pour plus d'informations, reportez-vous à Comment fonctionne sys.exc_info ()?

import sys

def f(i):

    try:
        if i == 1:
            raise Exception
    except Exception as e:
        print "except -> " + str(sys.exc_info())
    finally:
        print "finally -> " + str(sys.exc_info())

def f1(i):
    if i == 0:
        try:
            raise Exception('abc')
        except Exception as e:
            pass

    f(i)

f1(0)
f1(1)

>>> 
finally -> (<type 'exceptions.Exception'>, Exception('abc',), <traceback object at 0x02A33940>)
except -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x02A33990>)
finally -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x02A33990>)

J'espère que cela rend les choses un peu plus claires.

4

Vous voudrez le faire dans la clause except, pas pour finalement.

Voir: http://www.doughellmann.com/articles/Python-Exception-Handling/

2
Josh

Définissez simplement une variable vide pour une éventuelle exception avant le bloc tryexcept:

import sys

exception = None

try:
    result = 1/0
except ZeroDivisionError as e:
    exception = sys.exc_info()  # or "e"
finally:
    if exception:
        print(exception)
    else:
        print('Everything is fine')

Testé sur Python 3.6

0
MaxCore