2009-10-23 10 views

Respuesta

58

No, al tiempo finallysys.exc_info es todo-nada, si se ha producido una excepción o no. Uso: se ejecutará

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 
+0

Gracias. sys.exc_info (en una cláusula except) es lo que necesito – Goutham

+0

A partir de Python 3.?, puede acceder a 'sys.exc_info' dentro del bloque' finally: '. – Kentzo

+0

@Kentzo Acabo de probarlo en Python 3.6. 'sys.exc_info()' returns '(None, None, None)' en el bloque finally cuando generó una excepción. – Jonathan

10

El bloque finally independientemente de si ha generado una excepción o no, así como señala Josh, es muy probable que no quiere estar manejando allí.

Si realmente necesita el valor de una excepción que se planteó, entonces debe detectar la excepción en un bloque except, y manejarla apropiadamente o volver a subirla, y luego usar ese valor en el bloque finally - - con la expectativa de que nunca se haya establecido, si no se planteó ninguna excepción durante la ejecución.

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 
3

En realidad, otras respuestas son un poco vagas. Por lo tanto, déjame aclararlo. Siempre puede invocar sys.exc_info() desde el bloque finally. Sin embargo, su salida variará dependiendo de si la excepción ha sido realmente levantada.

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>) 

Por lo tanto, siempre es posible saber en bloque finally, si se eleva la excepción, si se trata de la primera función de nivel. Pero sys.exc_info() se comportará de manera diferente cuando la duración de la pila de llamadas excede de 1, como se muestra en el ejemplo siguiente. Para obtener más información, consulte How sys.exc_info() works?

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>) 

espero, que hace las cosas poco más claro.

+1

Esto es cierto solo para python2. – coldfix

+0

@coldfix ¿Quisiste decir que esto solo es cierto para python3? –

+1

No, ejecuto el script en python2 y python3. En python3 (después de solucionar problemas sintácticos menores), la salida para 'f (1)' es 'finally -> (None, None, None)', por lo que no puede obtener la excepción en el bloque finally tan fácil. – coldfix

0

apenas define una variable en blanco para posible excepción antes del bloque 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') 

probado en Python 3.6

Cuestiones relacionadas