statement - En Python, si regreso dentro de un bloque "con", ¿el archivo aún se cerrará?
with python español (3)
Sí, actúa como el bloque finally
después de un bloque try
, es decir, siempre se ejecuta (a menos que el proceso de python finalice de una manera inusual, por supuesto).
También se menciona en uno de los ejemplos de PEP-343 que es la especificación para la declaración with
:
with locked(myLock):
# Code here executes with myLock held. The lock is
# guaranteed to be released when the block is left (even
# if via return or by an uncaught exception).
Algo que vale la pena mencionar es, sin embargo, que no se pueden capturar fácilmente las excepciones lanzadas por la llamada a open()
sin poner todo el bloque dentro de un try..except
bloque que generalmente no es lo que uno quiere.
Considera lo siguiente:
with open(path, mode) as f:
return [line for line in f if condition]
¿El archivo se cerrará correctamente, o el uso de return
alguna manera omite el administrador de contexto ?
Sí. De manera más general, el método __exit__
de un Gestor de Contexto de Statement se llamará en caso de que se produzca un return
desde dentro del contexto. Esto se puede probar con lo siguiente:
class MyResource:
def __enter__(self):
print(''Entering context.'')
return self
def __exit__(self, *exc):
print(''EXITING context.'')
def fun():
with MyResource():
print(''Returning inside with-statement.'')
return
print(''Returning outside with-statement.'')
fun()
El resultado es:
Entering context.
Returning inside with-statement.
EXITING context.
El resultado anterior confirma que se llamó __exit__
pesar del return
anticipado. Como tal, el administrador de contexto no se pasa por alto.
Sí.
def example(path, mode):
with open(path, mode) as f:
return [line for line in f if condition]
..es más o menos equivalente a:
def example(path, mode):
f = open(path, mode)
try:
return [line for line in f if condition]
finally:
f.close()
Más exactamente, el método __exit__
en un administrador de contexto siempre se llama al salir del bloque (independientemente de las excepciones, devoluciones, etc.). El método __exit__
del objeto de __exit__
solo llama a f.close()
(por ejemplo, aquí en CPython )