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
with
declaración no rompe mágicamente unatry...except
declaració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...except
bloques adicionales dentrowith
para 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
with
declaració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...except
declaració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
with
no tiene unaexcept
cláusula:El
__exit__
método de un administrador de contexto , si regresa,False
volverá a generar el error cuando finalice. Si regresaTrue
, lo suprimirá. Elopen
incorporado__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 atrapaBaseException
y 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
with
declaración compuestaDiferenciar entre excepciones que ocurren en una
with
declaració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__
with
ContextManager.__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
with
en atry .. except
no es suficiente. Considere el siguiente ejemplo (usandoValueError
como ejemplo pero, por supuesto, podría ser sustituido por cualquier otro tipo de excepción):Aquí
except
capturará 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 delwith
inicio comenzó a ejecutarse (es decir, diferenciar entre__enter__
y los demás):La parte difícil es diferenciar entre las excepciones que se originan
BLOCK
y__exit__
porque sewith
pasará 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 unaexcept
cláusula general en el cuerpo del testamento simplemente no se ejecutará).with
archivo para almacenar cualquier posible excepción que de otro modo hubiera pasado desapercibida y compararla con la capturada en el exteriorexcept
más adelante; si son iguales, esto significa que el origen fueBLOCK
o de lo contrario lo fue__exit__
(en caso de que__exit__
suprima la excepción al devolver un valor verdadero lo más externoexcept
Enfoque alternativo utilizando la forma equivalente mencionada en PEP 343
PEP 343 - La declaración "con" especifica una versión equivalente "no con" de la
with
declaración. Aquí podemos envolver fácilmente las diversas partestry ... except
y 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
with
en untry ... except
bloque 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