Para mi vergüenza, no puedo entender cómo manejar la excepción para la declaración 'con' python. Si tengo un código:
with open("a.txt") as f:
print f.readlines()
Realmente quiero manejar 'excepción de archivo no encontrado' 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 declaración try / except no funciona más: no se genera una excepción. ¿Qué puedo hacer para procesar la falla dentro de la declaración 'con' de una manera pitónica?
python
exception-handling
grigoryvp
fuente
fuente

withdeclaración no rompe mágicamente unatry...exceptdeclaración circundante .Respuestas:
Si desea un manejo diferente de los errores de la llamada abierta frente al código de trabajo, puede hacer lo siguiente:
fuente
try...exceptbloques adicionales dentrowithpara estar más cerca de la fuente de una excepción que no tiene nada que veropen().La mejor manera "Pythonic" de hacer esto, explotando la
withdeclaración, se enumera como el Ejemplo # 6 en PEP 343 , que proporciona los antecedentes de la declaración.Usado de la siguiente manera:
fuente
try...exceptdeclaración.La declaración with ha estado disponible sin la
__future__importación desde Python 2.6 . Puede obtenerlo tan pronto como Python 2.5 (¡pero en este punto es hora de actualizar!) Con:Aquí está lo más cercano a corregir que tienes. Ya casi estás allí, pero
withno tiene unaexceptcláusula:El
__exit__método de un administrador de contexto , si regresa,Falsevolverá a generar el error cuando finalice. Si regresaTrue, lo suprimirá. Elopenincorporado__exit__no regresaTrue, por lo que solo debe anidarlo en un intento, excepto el bloque:Y repetitivo estándar: no use un simple
except:que atrapaBaseExceptiony cualquier otra posible excepción y advertencia. Sea al menos tan específico comoException, y para este error, tal vez atrapeIOError. Solo detecte errores que esté preparado para manejar.Entonces, en este caso, harías:
fuente
Diferenciar entre los posibles orígenes de excepciones planteadas a partir de una
withdeclaración compuestaDiferenciar entre excepciones que ocurren en una
withdeclaración es complicado porque pueden originarse en diferentes lugares. Se pueden generar excepciones desde cualquiera de los siguientes lugares (o funciones llamadas allí):ContextManager.__init__ContextManager.__enter__withContextManager.__exit__Para obtener más detalles, consulte la documentación sobre Tipos de Context Manager .
Si queremos distinguir entre estos diferentes casos, simplemente envolviendo el
withen atry .. exceptno es suficiente. Considere el siguiente ejemplo (usandoValueErrorcomo ejemplo pero, por supuesto, podría ser sustituido por cualquier otro tipo de excepción):Aquí
exceptcapturará excepciones que se originan en los cuatro lugares diferentes y, por lo tanto, no permite distinguir entre ellas. Si movemos la instanciación del objeto del administrador de contexto fuera delwith, podemos distinguir entre__init__yBLOCK / __enter__ / __exit__:Efectivamente, esto solo ayudó con la
__init__parte, pero podemos agregar una variable centinela adicional para verificar si el cuerpo delwithinicio comenzó a ejecutarse (es decir, diferenciar entre__enter__y los demás):La parte difícil es diferenciar entre las excepciones que se originan
BLOCKy__exit__porque sewithpasará una excepción que escapa del cuerpo de la voluntad a la__exit__cual puede decidir cómo manejarla (ver los documentos ). Sin embargo__exit__, si surge, la excepción original será reemplazada por la nueva. Para tratar estos casos, podemos agregar unaexceptcláusula general en el cuerpo del testamento simplemente no se ejecutará).witharchivo para almacenar cualquier posible excepción que de otro modo hubiera pasado desapercibida y compararla con la capturada en el exteriorexceptmás adelante; si son iguales, esto significa que el origen fueBLOCKo de lo contrario lo fue__exit__(en caso de que__exit__suprima la excepción al devolver un valor verdadero lo más externoexceptEnfoque alternativo utilizando la forma equivalente mencionada en PEP 343
PEP 343 - La declaración "con" especifica una versión equivalente "no con" de la
withdeclaración. Aquí podemos envolver fácilmente las diversas partestry ... excepty así diferenciar entre las diferentes fuentes de error potenciales:Por lo general, un enfoque más simple funcionará bien
La necesidad de tal manejo de excepciones especiales debe ser bastante rara y normalmente envolver todo
withen untry ... exceptbloque será suficiente. Especialmente si las diversas fuentes de error están indicadas por diferentes tipos de excepción (personalizados) (los gestores de contexto deben diseñarse en consecuencia) podemos distinguir fácilmente entre ellos. Por ejemplo:fuente