Sobre la captura de CUALQUIER excepción

696

¿Cómo puedo escribir un try/ exceptbloque que capture todas las excepciones?

user469652
fuente
44
En la mayoría de los casos, probablemente esté haciendo algo mal si está tratando de detectar alguna excepción. Quiero decir que simplemente puedes escribir mal algo en tu código e incluso no lo sabrás. Es una buena práctica atrapar excepciones específicas.
vwvolodya
12
Para ser más precisos, capturar todas las excepciones posibles es solo un problema si se capturan en silencio. Es difícil pensar en dónde más es apropiado este enfoque, aparte de dónde se imprimen sys.stderry posiblemente se registran los mensajes de error detectados . Esa es una excepción perfectamente válida y común.
Evgeni Sergeev
intentaste try: whatever() except Exception as e: exp_capture() :?
Charlie Parker

Respuestas:

564

Puedes pero probablemente no deberías:

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

Sin embargo, esto también detectará excepciones como KeyboardInterrupty generalmente no quieres eso, ¿verdad? A menos que vuelva a aumentar la excepción de inmediato, consulte el siguiente ejemplo de los documentos :

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
Tim Pietzcker
fuente
15
Su última declaración no es verdadera, debe decir explícitamente except Exception:lo desnudo, excepto que también tendrá que capturar las Excepciones Base.
Pykler
77
Realmente deberías imprimir en stderr.
nyuszika7h
41
Estoy muy, muy en desacuerdo con la afirmación "no debería". Deberías hacerlo con moderación. Hay momentos en los que está tratando con bibliotecas de terceros (¡a veces cargadas dinámicamente!) Que se han vuelto completamente locas con excepciones y rastrearlas todas puede ser una tarea muy dolorosa, y si se pierde solo una, tiene una muy Gran error doloroso en su sistema. Dicho esto, es bueno rastrear tantos como puedas y manejarlos adecuadamente y luego tener una captura de respaldo para todos los que echas de menos.
Blaze
26
Lo que también me parece extraño es que en un lenguaje de escritura de pato donde no declaras variables de instancia, de repente está muy preocupado por no escribir todas tus excepciones. Hmm!
Blaze
835

Además de una except:cláusula simple (que como otros han dicho que no debe usar), simplemente puede atrapar Exception:

import traceback
import logging

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

Normalmente, solo consideraría hacer esto en el nivel más externo de su código si, por ejemplo, desea manejar cualquier excepción no detectada antes de finalizar.

La ventaja de except ExceptionOver the bare exceptes que hay algunas excepciones que no atraparán, más obviamente KeyboardInterrupty SystemExit: si las atrapó y se las tragó, podría dificultar que cualquiera salga de su script.

Duncan
fuente
Tenía lo mismo en mi mente, pero es una desventaja, supongamos que son dos errores cuando se detecta una vez y, excepto que solo está imprimiendo, saldrá del bloque de prueba y nunca sabrá el segundo error. .
66
Para cualquiera que se pregunte, totalmente contrario a mi expectativa, esto aún atrapará subclases no excepcionales como ints, al menos en python 2.x.
Joseph Garvin el
55
@JosephGarvin, eso es incorrecto, es decir, esto no detectará "no excepciones" que no subclasifiquen Exception. Tenga en cuenta que es imposible plantear un intcomo una excepción, e intentar hacerlo genera una TypeErrorexcepción, que es lo que sería captado por la except Exceptioncláusula adjunta en tal caso. Por otro lado, una clase de estilo antiguo se puede generar y califica como una "no excepción" que no es una subclase Exception; esto se captará con una exceptcláusula simple pero no con una except Exceptioncláusula.
Yoel
44
@JosephGarvin revise esta entrada del blog: chris-lamb.co.uk/posts/no-one-expects-string-literal-exception Estoy con @Yoel en este caso, su prueba acaba de enmascarar elTypeError
Duncan
2
@CharlieParker no hay nada de malo en atraparlos si eso es lo que quieres pero en su mayoría no. Llamar sys.exit()generalmente significa que espera que la aplicación finalice, pero si atrapa SystemExit no lo hará. Del mismo modo, si presiona control-C en un script en ejecución (Ctrl-break en Windows), espera que el programa se detenga, no detecte el error y continúe. Pero puede atrapar cualquiera / ambos de estos si desea hacer la limpieza antes de existir.
Duncan
100

Puede hacer esto para manejar excepciones generales

try:
    a = 2/0
except Exception as e:
    print e.__doc__
    print e.message
vwvolodya
fuente
8
Es posible que esto no capture todas las excepciones, ya que la clase base para todas las excepciones es BaseException y he encontrado código de producción que no está en la familia de la clase Exception. Consulte docs.python.org/3/library/… para obtener detalles sobre esto.
DDay
44
Esto no captura todas las excepciones.
Andy_A̷n̷d̷y̷
66
Técnicamente, debería capturar todas las excepciones que no sean del sistema. De los documentos @DDay vinculados: " excepción BaseException: la clase base para todas las excepciones integradas. No debe ser heredada directamente por las clases definidas por el usuario (para eso, use Exception)". A menos que esté trabajando con código que ignore esto, o necesite detectar excepciones que salgan del sistema, lo anterior debería estar bien para usar.
Peter Cassetta
@PeterCassetta ¿cuándo querría atrapar el sistema al salir de las excepciones? Parece el hilo común en la pregunta que no queremos atraparlos, pero no entiendo por qué. ¿Por qué no usualmente?
Charlie Parker
68

Para capturar todas las excepciones posibles, captura BaseException. Está en la parte superior de la jerarquía de excepciones:

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

Pero como otras personas mencionaron, generalmente no necesitaría esto, solo para casos específicos.

gitaarik
fuente
1
¿Desea guardar el progreso de un trabajo de larga duración después de presionar Ctrl-C que inusual?
BallpointBen
54

Ejemplo muy simple, similar al que se encuentra aquí:

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

Si está intentando atrapar TODAS las excepciones, coloque todo su código dentro de la instrucción "try:", en lugar de 'print "Realizando una acción que puede lanzar una excepción".

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."

En el ejemplo anterior, vería la salida en este orden:

1) Realizar una acción que puede arrojar una excepción.

2) Finalmente se llama directamente después de ejecutar la declaración de prueba, ya sea que se lance una excepción o no.

3) "¡Se produjo una excepción!" o "¡Todo se ve genial!" dependiendo de si se lanzó una excepción.

¡Espero que esto ayude!

Joshua Burns
fuente
26

Hay varias formas de hacer esto en particular con Python 3.0 y superior

Enfoque 1

Este es un enfoque simple pero no recomendado porque no sabría exactamente qué línea de código está lanzando realmente la excepción:

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

bad_method()

Enfoque 2

Se recomienda este enfoque porque proporciona más detalles sobre cada excepción. Incluye:

  • Número de línea para su código
  • Nombre del archivo
  • El error real en forma más detallada

El único inconveniente es que el tracback debe importarse.

import traceback

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

bad_method()
grepit
fuente
21

Acabo de descubrir este pequeño truco para probar si hay nombres de excepción en Python 2.7. A veces he manejado excepciones específicas en el código, por lo que necesitaba una prueba para ver si ese nombre está dentro de una lista de excepciones manejadas.

try:
    raise IndexError #as test error
except Exception as e:
    excepName = type(e).__name__ # returns the name of the exception
Danilo
fuente
2
try:
    whatever()
except:
    # this will catch any exception or error

Vale la pena mencionar que esto no es una codificación Python adecuada. Esto detectará también muchos errores que quizás no desee detectar.

Yuval Adam
fuente
solo use, excepto no haga todas las excepciones como se menciona en algunas otras respuestas. Tienes que usar BaseException para este propósito, pero como dijiste, nadie debería detectar todas las excepciones como esta. Supongo que está bien para empezar si el objetivo es agregar más granular excepto durante el desarrollo, pero no creo que sea ...
Pyglouthon