python sintaxis - Cómo ignorar apropiadamente las excepciones




anidados except (10)

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

Esto le ayudará a imprimir qué 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]

...

reg, Tilokchan

Cuando solo quieres hacer un intento, 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 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 intento no causa una excepción.


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

Manejo de una excepción en Python: si tiene algún código sospechoso que puede provocar 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

¿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 la docs :

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 programa 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 intento / 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 es operativa. 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.

Esta es 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 desee 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 

En Python, manejamos excepciones similares a otro lenguaje, 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...


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


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 pila, desea algo como esto:

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

Usted podría hacer dos decoradores independientes que hacen lo que usted quiere, como se ilustra a continuación directamente. Observe el uso de *args, **kwargsen la declaración de la wrapped()función que admite la función decorada con múltiples argumentos (que no es realmente necesario para la say()función de ejemplo , pero se incluye para generalidad)

Por razones similares, el functools.wrapsdecorador se usa para cambiar los meta atributos de la función envuelta para que sean los del decorado. Esto hace que los mensajes de error y la documentación de la función incorporada ( func.__doc__) sean los de la función decorada en lugar de wrapped()'s.

from functools import wraps

def makebold(fn):
    @wraps(fn)
    def wrapped(*args, **kwargs):
        return "<b>" + fn(*args, **kwargs) + "</b>"
    return wrapped

def makeitalic(fn):
    @wraps(fn)
    def wrapped(*args, **kwargs):
        return "<i>" + fn(*args, **kwargs) + "</i>"
    return wrapped

@makebold
@makeitalic
def say():
    return 'Hello'

print(say())  # -> <b><i>Hello</i></b>

Refinamientos

Como puede ver, hay muchos códigos duplicados en estos dos decoradores. Dada esta similitud, sería mejor que usted creara una genérica que en realidad era una fábrica de decoradores; en otras palabras, un decorador que crea otros decoradores. De esa manera, habría menos repetición de código y permitiría seguir el principio DRY .

def html_deco(tag):
    def decorator(fn):
        @wraps(fn)
        def wrapped(*args, **kwargs):
            return '<%s>' % tag + fn(*args, **kwargs) + '</%s>' % tag
        return wrapped
    return decorator

@html_deco('b')
@html_deco('i')
def greet(whom=''):
    return 'Hello' + (' ' + whom) if whom else ''

print(greet('world'))  # -> <b><i>Hello world</i></b>

Para hacer que el código sea más legible, puede asignar un nombre más descriptivo a los decoradores generados en fábrica:

makebold = html_deco('b')
makeitalic = html_deco('i')

@makebold
@makeitalic
def greet(whom=''):
    return 'Hello' + (' ' + whom) if whom else ''

print(greet('world'))  # -> <b><i>Hello world</i></b>

O incluso combinarlos de esta manera:

makebolditalic = lambda fn: makebold(makeitalic(fn))

@makebolditalic
def greet(whom=''):
    return 'Hello' + (' ' + whom) if whom else ''

print(greet('world'))  # -> <b><i>Hello world</i></b>

Eficiencia

Si bien los ejemplos anteriores funcionan correctamente, el código generado implica una gran cantidad de gastos generales en forma de llamadas de funciones extrañas cuando se aplican varios decoradores a la vez. Esto puede no importar, dependiendo del uso exacto (que podría estar vinculado a E / S, por ejemplo).

Si la velocidad de la función decorada es importante, la sobrecarga se puede mantener en una sola función de función adicional escribiendo una función de fábrica de decorador ligeramente diferente que implementa la adición de todas las etiquetas a la vez, para que pueda generar un código que evite las funciones adicionales llamadas mediante el uso de decoradores separados para cada etiqueta.

Esto requiere más código en el decorador en sí, pero solo se ejecuta cuando se aplica a definiciones de funciones, no más tarde cuando se llaman ellas mismas. Esto también se aplica cuando se crean nombres más legibles utilizando lambdafunciones como se ilustró anteriormente. Muestra:

def multi_html_deco(*tags):
    start_tags, end_tags = [], []
    for tag in tags:
        start_tags.append('<%s>' % tag)
        end_tags.append('</%s>' % tag)
    start_tags = ''.join(start_tags)
    end_tags = ''.join(reversed(end_tags))

    def decorator(fn):
        @wraps(fn)
        def wrapped(*args, **kwargs):
            return start_tags + fn(*args, **kwargs) + end_tags
        return wrapped
    return decorator

makebolditalic = multi_html_deco('b', 'i')

@makebolditalic
def greet(whom=''):
    return 'Hello' + (' ' + whom) if whom else ''

print(greet('world'))  # -> <b><i>Hello world</i></b>




python exception exception-handling try-except