Captura de una excepción al usar una statement ‘with’ de Python

Para mi vergüenza, no puedo averiguar cómo manejar la excepción para la statement ‘with’ de python. Si tengo un código:

with open("a.txt") as f: print f.readlines() 

Tengo muchas ganas de manejar ‘archivo no encontrado excepción’ para hacer algo. Pero no puedo escribir

 with open("a.txt") as f: print f.readlines() except: print 'oops' 

y no puedo escribir

 with open("a.txt") as f: print f.readlines() else: print 'oops' 

encerrar ‘con’ en una statement de prueba / excepción no funciona: la excepción no se produce. ¿Qué puedo hacer para procesar el error dentro de la statement ‘with’ de forma Pythonic?

 from __future__ import with_statement try: with open( "a.txt" ) as f : print f.readlines() except EnvironmentError: # parent of IOError, OSError *and* WindowsError where available print 'oops' 

Si desea una gestión diferente de los errores de la llamada abierta frente al código de trabajo, podría hacerlo:

 try: f = open('foo.txt') except IOError: print('error') else: with f: print f.readlines() 

La mejor manera “Pythonic” de hacer esto, explotando la statement with , está listada como Ejemplo # 6 en PEP 343 , que proporciona el fondo de la statement.

 @contextmanager def opened_w_error(filename, mode="r"): try: f = open(filename, mode) except IOError, err: yield None, err else: try: yield f, None finally: f.close() 

Utilizado de la siguiente manera:

 with opened_w_error("/etc/passwd", "a") as (f, err): if err: print "IOError:", err else: f.write("guido::0:0::/:/bin/sh\n") 

Captura de una excepción al usar una statement ‘with’ de Python

La instrucción with ha estado disponible sin la importación __future__ desde Python 2.6 . Puedes obtenerlo tan pronto como Python 2.5 (¡pero en este momento es el momento de actualizar!) Con:

 from __future__ import with_statement 

Aquí está lo más cercano a corregir que tienes. Ya casi llegas, pero sin una cláusula de except :

 with open("a.txt") as f: print(f.readlines()) except: # <- with doesn't have an except clause. print('oops') 

El método __exit__ de un administrador de __exit__ , si devuelve False volverá a generar el error cuando finalice. Si devuelve True , lo suprimirá. El __exit__ del __exit__ no devuelve True , por lo que solo debe __exit__ en un try, excepto en el bloque:

 try: with open("a.txt") as f: print(f.readlines()) except Exception as error: print('oops') 

Y la BaseException estándar: no use un simple except: que BaseException y cualquier otra excepción y advertencia posible. Sea al menos tan específico como Exception , y para este error, tal vez IOError . Solo captura errores que estés preparado para manejar.

Así que en este caso, harías:

 >>> try: ... with open("a.txt") as f: ... print(f.readlines()) ... except IOError as error: ... print('oops') ... oops 

Otra alternativa podría ser verificar si el archivo existe primero y luego continuar with statement. Ejemplo:

 import os if os.path.exists(file_path): with open("a.txt") as f: # proceed as usual print f.readlines() elif not os.path.exists(file_path): # check first if file exsits print("file not found") 

EDITAR: el código anterior solo verifica si el archivo existe, ya que no cubre otros casos posibles. He recurrido al manejo de excepciones estándar

 try: with open("a.txt") as f: #business as usual except Exception as e: print "oops, handle exception: ", e