Cómo ignorar apropiadamente las excepciones

Cuando solo quieres hacer un bash, 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 

 try: doSomething() except: pass 

o

 try: doSomething() except Exception: pass 

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

En general, se considera una práctica recomendada solo detectar los errores en los que está interesado. En el caso de shutil.rmtree es probable que 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é? Digamos que usted (de alguna manera) pasa accidentalmente a la función un número entero en lugar de una cadena, como:

 shutil.rmtree(2) 

Le dará el error Error del tipo : coacción a Unicode: se necesita una cadena o un búfer, se encontró” , probablemente no quiera ignorarlo, lo que puede ser difícil de depurar.

Si definitivamente desea ignorar todos los errores, capture Exception lugar de una simple except: De nuevo, ¿por qué?

Al no especificar una excepción, se SystemExit todas las excepciones, incluida la excepción SystemExit que, por ejemplo, sys.exit() utiliza:

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

Compare esto con lo siguiente, que sale correctamente:

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

Si desea escribir un código de mejor comportamiento, la excepción OSError puede representar varios errores, pero en el ejemplo anterior solo queremos ignorar Errno 2 , por lo que 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 puede import errno y cambiar if a if e.errno == errno.ENOENT:

Cuando solo quieres hacer un try catch sin manejar la excepción, ¿cómo lo haces en Python?

Depende de lo que quieras decir con “manejo”.

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

Si quiere decir que desea realizar una acción en una excepción sin impedir que la excepción suba la stack, entonces quiere algo como esto:

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

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á la confirmación que lo agregó: http://hg.python.org/cpython/rev/406b47c64480

Y aquí está el autor, Raymond Hettinger, hablando de esto y de todo otro tipo de picor 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 

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" 

… del 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 

¿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 para el 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 en él haciendo lo siguiente, y verá que también puede permitir la funcionalidad de los errores.

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

Como esto solo cubre el caso estrecho del ejemplo, demostraré además cómo manejar esto si esos argumentos de palabras clave no existieran.

Enfoque general

Dado que lo anterior solo cubre el caso estrecho del ejemplo, demostraré además cómo manejar esto si esos argumentos de palabras clave no existieran.

Nuevo en Python 3.4:

Puede importar el administrador de contexto de suppress :

 from contextlib import suppress 

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

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

FileNotFoundError silenciosamente un FileNotFoundError :

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

De los documentos :

Al igual que con cualquier otro mecanismo que suprima por completo las excepciones, este administrador de contexto debe usarse solo para cubrir errores muy específicos en los que se sabe que continuar con la ejecución del progtwig es lo correcto.

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

Si también desea que su código funcione en Python 2, consulte la siguiente sección:

Python 2 y 3:

Cuando solo quieres hacer un bash / 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 statement que no funciona. Pero cuando haces un except BaseException: es lo mismo que hacer, except BaseException: que incluye GeneratorExit , KeyboardInterrupt , y SystemExit , y en general, no quieres capturar esas cosas.

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

Aquí hay parte de la jerarquía de excepciones de Python (2) y, como puede ver, si detecta excepciones más generales, puede ocultar los 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.

Podemos obtener ese número de error específico de la biblioteca errno y volver a subir si no lo tenemos:

 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 genera la excepción original, que es probablemente lo que desea en este caso. Escrito de forma más concisa, ya que no necesitamos pass explícitamente 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 

Cuando solo quieres hacer un try catch sin manejar la excepción, ¿cómo lo haces en Python?

Esto le ayudará a imprimir cuál es la excepción: (es decir, intente capturar sin manejar la excepción e imprima la excepción).

 import sys try: doSomething() except: print "Unexpected error:", sys.exc_info()[0] 
 try: doSomething() except Exception: pass else: stuffDoneIf() TryClauseSucceeds() 

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

En Python, manejamos excepciones similares a otro lenguaje, pero la diferencia es una diferencia de syntax, por ejemplo,

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

Necesitaba ignorar los errores en varios comandos y joder , resolví el problema

 import fuckit @fuckit def helper(): print('before') 1/0 print('after1') 1/0 print('after2') helper() 

Simplemente levante la excepción relevante, así:

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

Tan sencillo como eso. 🙂

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