Pregunta Cómo ignorar adecuadamente las excepciones


Cuando solo quieres probar, excepto que sin manejar la excepción, ¿cómo lo haces en Python?

¿Es la siguiente la forma correcta de hacerlo?

try:
    shutil.rmtree(path)
except:
    pass

607
2018-04-08 16:23


origen


Respuestas:


try:
  doSomething()
except: 
  pass

o

try:
  doSomething()
except Exception: 
  pass

La diferencia es que el primero también atrapará KeyboardInterrupt, SystemExit y cosas por el estilo, que se derivan directamente de exceptions.BaseExceptionno exceptions.Exception.
 Ver la documentación para más detalles:


845
2018-04-08 16:25



En general, se considera la mejor práctica detectar solo los errores que le interesan. En el caso de shutil.rmtree es probable OSError:

>>> shutil.rmtree("/fake/dir")
Traceback (most recent call last):
    [...]
OSError: [Errno 2] No such file or directory: '/fake/dir'

Si quieres ignorar silenciosamente ese error, harías:

try:
    shutil.rmtree(path)
except OSError:
    pass

¿Por qué? Supongamos que (de alguna manera) accidentalmente pasa la función un número entero en lugar de una cadena, como:

shutil.rmtree(2)

Dará el error "TypeError: coercing a Unicode: necesita cadena o búfer, int found" - Probablemente no desee ignorar eso, que puede ser difícil de depurar.

Si tu seguro quiere ignorar todos los errores, atrapar Exception en lugar de un desnudo except: declaración. Nuevamente, ¿por qué?

Sin especificar una captura de excepción cada excepción, incluido el SystemExit excepción que, por ejemplo, sys.exit() usos:

>>> try:
...     sys.exit(1)
... except:
...     pass
... 
>>>

Compare esto con lo siguiente, que sale correctamente:

>>> try:
...     sys.exit(1)
... except Exception:
...     pass
... 
shell:~$ 

Si quieres escribir un código de comportamiento cada vez mejor, OSError excepción puede representar varios errores, pero en el ejemplo anterior solo queremos ignorar Errno 2, entonces podríamos ser aún más específicos:

try:
    shutil.rmtree(path)
except OSError, e:
    if e.errno == 2:
        # suppress "No such file or directory" error
        pass
    else:
        # reraise the exception, as it's an unexpected error
        raise

También podrías import errno y cambiar el if a if e.errno == errno.ENOENT:


117
2018-04-09 21:48



Cuando solo quieres hacer una captura de prueba sin manejar la excepción, ¿cómo lo haces en Python?

Depende de lo que quiere decir con "manejo".

Si intenta atraparlo sin realizar ninguna acción, el código que publicó funcionará.

Si quieres decir que quieres tomar medidas en una excepción sin detener la excepción de subir la pila, entonces quieres algo como esto:

try:
    do_something()
except:
    handle_exception()
    raise  #re-raise the exact same exception that was thrown

106
2018-04-08 16:32



Primero cito la respuesta de Jack O'Connor de este hilo. El hilo de referencia se cerró, así que escribo aquí:

"Hay una nueva forma de hacerlo en Python 3.4:

from contextlib import suppress

with suppress(Exception):
    # your code

Aquí está el compromiso que lo agregó: http://hg.python.org/cpython/rev/406b47c64480

Y aquí está el autor, Raymond Hettinger, hablando de esto y de todo tipo de pitidos de Python: https://youtu.be/OSGv2VnC0go?t=43m23s

Mi adición a esto es el equivalente de Python 2.7:

from contextlib import contextmanager

@contextmanager
def ignored(*exceptions):
    try:
        yield
    except exceptions:
        pass

Entonces lo usas como en Python 3.4:

with ignored(Exception):
    # your code

64
2017-09-07 20:55



Por completitud:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print "division by zero!"
...     else:
...         print "result is", result
...     finally:
...         print "executing finally clause"

...desde el tutorial de Python.

También tenga en cuenta que puede capturar la excepción de esta manera:

>>> try:
...     this_fails()
... except ZeroDivisionError as detail:
...     print 'Handling run-time error:', detail

54
2018-03-05 23:02



¿Cómo ignorar adecuadamente las excepciones?

Hay varias maneras de hacer esto.

Sin embargo, la elección del ejemplo tiene una solución simple que no cubre el caso general.

Específico al ejemplo:

En lugar de

try:
    shutil.rmtree(path)
except:
    pass

Hacer esto:

shutil.rmtree(path, ignore_errors=True)

Este es un argumento específico para shutil.rmtree. Puede ver la ayuda haciendo lo siguiente, y verá que también puede permitir la funcionalidad en los errores.

>>> import shutil
>>> help(shutil.rmtree)

Como esto solo cubre el caso estricto del ejemplo, demostraré cómo manejar esto si esos argumentos de palabra clave no existieran.

Enfoque general

Como lo anterior solo cubre el caso estricto del ejemplo, demostraré cómo manejarlo si esos argumentos de palabra clave no existieran.

Nuevo en Python 3.4:

Puedes importar el suppress administrador de contexto:

from contextlib import suppress

Pero solo suprime la excepción más específica:

with suppress(FileNotFoundError):
    shutil.rmtree(path)

Ignorarás silenciosamente un FileNotFoundError:

>>> with suppress(FileNotFoundError):
...     shutil.rmtree('bajkjbkdlsjfljsf')
... 
>>> 

Desde el documentos:

Como con cualquier otro mecanismo que suprime por completo las excepciones,   este gestor de contexto debe usarse solo para cubrir errores muy específicos   donde se sabe que continuar silenciosamente con la ejecución del programa es   Es lo correcto.

Tenga en cuenta que suppress y FileNotFoundError solo están disponibles en Python 3.

Si también quieres que tu código funcione en Python 2, mira la siguiente sección:

Python 2 y 3:

Cuando solo quiere hacer una prueba / excepto sin manejar la excepción,   ¿cómo lo haces en Python?

¿Es la siguiente la forma correcta de hacerlo?

try :
    shutil.rmtree ( path )
except :
    pass

Para el código compatible con Python 2, pass es la forma correcta de tener una declaración que no sea operativa. Pero cuando haces un desnudo except:, eso es lo mismo que hacer except BaseException: que incluye GeneratorExit, KeyboardInterrupty SystemExit, y en general, no quieres atrapar esas cosas.

De hecho, debe ser tan específico al nombrar la excepción como pueda.

Aquí hay parte de Python (2) jerarquía de excepciones, y como puede ver, si detecta Excepciones más generales, puede ocultar problemas que no esperaba:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
... and so on

Probablemente quiera capturar un OSError aquí, y tal vez la excepción que no le importa es si no hay un directorio.

Nosotros podemos obtener ese número de error específico del errno biblioteca, y resubir si no tenemos eso:

import errno

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno == errno.ENOENT: # no such file or directory
        pass
    else: # we had an OSError we didn't expect, so reraise it
        raise 

Tenga en cuenta que un aumento simple plantea la excepción original, que es probablemente lo que quiere en este caso. Escrito de manera más concisa, ya que realmente no necesitamos explícitamente pass con código en el manejo de excepciones:

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno != errno.ENOENT: # no such file or directory
        raise 

40
2018-01-22 04:42



@ Cuando solo quieres hacer una captura de prueba sin manejar la excepción, ¿cómo lo haces en Python?

Esto le ayudará a imprimir qué excepción es: (es decir, intentar capturar sin manejar la excepción e imprimir la excepción).

import sys
....
tratar:
    hacer algo()
excepto:
    print "Error inesperado:", sys.exc_info () [0]

...

reg, Tilokchan


12
2017-10-12 05:36



try:
      doSomething()
except Exception: 
    pass
else:
      stuffDoneIf()
      TryClauseSucceeds()

FYI la cláusula else puede ir después de todas las excepciones y solo se ejecutará si el código en el intento no causa una excepción.


8
2017-11-19 22:35



En Python, manejamos excepciones similares a otros lenguajes, pero la diferencia es alguna diferencia de sintaxis, por ejemplo,

try:
    #Your code in which exception can occur
except <here we can put in a particular exception name>:
    # We can call that exception here also, like ZeroDivisionError()
    # now your code
# We can put in a finally block also
finally:
    # Your code...

3
2017-11-18 10:27



Simplemente aumento la excepción relevante, así como esto:

try:
     raise NameError('Joan')
 except NameError:
     print 'An exception just raised again by Joan!'
     raise

Tan sencillo como eso. :)

Para más detalles, lea esta documentación: https://docs.python.org/3.6/tutorial/errors.html


-1
2018-06-03 19:46



Manejando una excepción en Python: Si tiene algún código sospechoso que pueda generar una excepción, puede defender su programa colocando el código sospechoso en un bloque try:.

try:
    # Your statements .............
except ExceptionI:
    # Your statements.............
except ExceptionII:
    # Your statements..............
else:
   # Your statements

-1
2017-08-03 05:33