2011-08-18 14 views
20

En primer lugar, no estoy seguro de si mi enfoque es correcto, por lo que estoy abierto a una variedad de sugerencias.Se repite con frecuencia try/except en Python

Si las sentencias try/except se repiten con frecuencia en el código, ¿hay alguna forma de acortarlas o evitar escribirlas por completo?

try: 
    # Do similar thing 
    os.remove('/my/file') 
except OSError, e: 
    # Same exception handing 
    pass 

try: 
    # Do similar thing 
    os.chmod('/other/file', 0700) 
except OSError, e: 
    #Same exception handling 
    pass 

Por ejemplo, para las acciones de una línea se podría definir un envoltorio de manejo de excepciones y luego pasar una función lambda:

def may_exist(func): 
    "Work with file which you are not sure if exists.""" 
    try: 
     func() 
    except OSError, e: 
     # Same exception handling 
     pass 

may_exist(lambda: os.remove('/my/file')) 
may_exist(lambda: os.chmod('/other/file', 0700)) 

¿Este 'solución' simplemente hacer las cosas menos claro? ¿Debería escribir completamente todas las declaraciones try/except?

+0

posible duplicado de [Python:? Try-solo son la expresión] (http://stackoverflow.com/questions/7088009/python-try-except-as -an-expression) – agf

+0

Yo y @kindall respondimos esta pregunta muy amablemente ayer. – agf

+0

@agf: Esa pregunta parece parcialmente relacionada, gracias por enlazar. Sin embargo, la respuesta de Ned Batchelder parece tener la ventaja de que no hay necesidad de crear una función fuera del bloque de código para el cual se deben capturar excepciones. – sutre

Respuesta

24

La mejor forma de manejo de excepciones es abstracta con un gestor de contexto:

from contextlib import contextmanager 
@contextmanager 
def common_handling(): 
    try: 
     yield 
    finally: 
     # whatever your common handling is 

a continuación:

with common_handling(): 
    os.remove('/my/file') 

with common_handling(): 
    os.chmod('/other/file', 0700) 

Esto tiene el ventaja de que puede colocar declaraciones completas, y más de una de ellas, en cada bloque common_handling.

Tenga en cuenta, sin embargo, su necesidad de utilizar el mismo manejo una y otra vez se parece mucho a excepciones de manipulación. ¿Estás seguro de que necesitas hacer tanto?

+0

Creo que esto es exactamente lo que estaba buscando, pero podría estar superando las excepciones. En estos casos, quiero trabajar con archivos solo si existen. Podría verificar si existen de antemano (os.path.filexists), pero por lo que entiendo, ¿es mejor tratar de detectar excepciones en python? – sutre

+0

En ese caso, podría tener sentido capturar la * primera * excepción, y omitir todo el bloque de instrucciones con respecto a ese archivo si no existiera, pero permitir que todas las demás excepciones de las operaciones restantes se propaguen, ya que es poco probable que la falta de excepción en el primero seguido de una excepción en el segundo sea equivalente a la existencia del archivo. – SingleNegationElimination

+0

@TokenMacGuy: Gracias, eso tiene mucho sentido. Voy a ver cuál es la mejor manera de hacerlo. – sutre

2

Creo que su solución genérica está bien, pero yo no usaría esas lambdas en la parte inferior. Te recomiendo que pasa a la función y los argumentos como éste

def may_exist(func, *args): 
    "Work with file which you are not sure if exists.""" 
    try: 
     func(args) 
    except OSError, e: 
     # Same exception handling 
     pass 

may_exist(os.remove, '/my/file') 
may_exist(os.chmod, '/other/file', '0700') 
4

Probablemente sería más limpio para hacer may_exist un decorador:

from functools import wraps 
def may_exist(func): 
    @wraps(func): 
    def wrapper(*args, **kwds): 
     try: 
      return func(*args, **kwds) 
     except OSError: 
      pass 
    return wrapper 

Entonces usted puede hacer:

may_exist(os.remove)('/my/file') 
may_exist(os.chmod)('/other/file', 0700) 

para una llamada de una sola vez, o bien:

remove_if_exists = may_exist(os.remove) 
... 
remove_if_exists('somefile') 

si lo usa mucho.

1

¿Podría algo así como este trabajo:

def may_exist(func, *func_args): 
    try: 
     func(*func_args) 
    except OSError as e: 
     pass 
Cuestiones relacionadas