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 ?
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 ?
Respuestas:
Sí, actúa como el finally
bloque después de un try
bloque, es decir, siempre se ejecuta (a menos que el proceso de Python termine de una manera inusual, por supuesto).
También se menciona en uno de los ejemplos de PEP-343, que es la especificación de la with
declaración:
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).
Sin embargo, algo que vale la pena mencionar es que no se pueden detectar fácilmente las excepciones lanzadas por la open()
llamada sin poner todo el with
bloque dentro de un try..except
bloque que generalmente no es lo que uno quiere.
Process.terminate()
es uno de los pocos (¿el único?) Escenario que no garantiza la llamada de una finally
declaración: "Tenga en cuenta que los controladores de salida y finalmente las cláusulas, etc., no serán ejecutado."
with
pasa si devuelvo una expresión de generador desde dentro del bloque, la garantía se mantiene mientras el generador siga produciendo valores? durante todo el tiempo que lo haga referencia? Es decir, ¿necesito usar del
o asignar un valor diferente a la variable que contiene el objeto generador?
ValueError: I/O operation on closed file.
.
Si.
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 __exit__
método en un administrador de contexto siempre se llama al salir del bloque (independientemente de las excepciones, devoluciones, etc.). El __exit__
método del objeto de archivo solo llama f.close()
(por ejemplo, aquí en CPython )
finally
keywrod es: def test(): try: return True; finally: return False
.
Si. En términos más generales, el __exit__
método de un Administrador de contexto de declaración con se llamará en el caso de 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 __exit__
fue llamado a pesar de lo temprano return
. Como tal, el administrador de contexto no se omite.
Sí, pero puede haber algún efecto secundario en otros casos, ya que podría hacer algo (como búfer de lavado) en el __exit__
bloque
import gzip
import io
def test(data):
out = io.BytesIO()
with gzip.GzipFile(fileobj=out, mode="wb") as f:
f.write(data)
return out.getvalue()
def test1(data):
out = io.BytesIO()
with gzip.GzipFile(fileobj=out, mode="wb") as f:
f.write(data)
return out.getvalue()
print(test(b"test"), test1(b"test"))
# b'\x1f\x8b\x08\x00\x95\x1b\xb3[\x02\xff' b'\x1f\x8b\x08\x00\x95\x1b\xb3[\x02\xff+I-.\x01\x00\x0c~\x7f\xd8\x04\x00\x00\x00'
else
podría agregarsewith
para resolver esetry with except
problema. editar: agregado al idioma