Considere o seguinte:
with open(path, mode) as f:
return [line for line in f if condition]
O arquivo será fechado corretamente ou o uso de return
alguma forma ignora o gerenciador de contexto ?
Considere o seguinte:
with open(path, mode) as f:
return [line for line in f if condition]
O arquivo será fechado corretamente ou o uso de return
alguma forma ignora o gerenciador de contexto ?
Respostas:
Sim, ele age como o finally
bloco após um try
bloco, ou seja, sempre é executado (a menos que o processo python termine de uma maneira incomum, é claro).
Também é mencionado em um dos exemplos de PEP-343, que é a especificação para a with
declaração:
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 a pena mencionar é que você não pode capturar facilmente exceções geradas pela open()
chamada sem colocar todo o with
bloco dentro de um try..except
bloco que geralmente não é o que se deseja.
Process.terminate()
é um dos poucos (o único?) Cenário que não garante a chamada de uma finally
declaração: "Observe que os manipuladores de saída e, finalmente, as cláusulas etc., não serão executado."
with
bloco, a garantia se mantém enquanto o gerador continuar produzindo valores? enquanto alguma coisa referenciar isso? del
Ou seja, eu preciso usar ou atribuir um valor diferente para a variável que contém o objeto gerador?
ValueError: I/O operation on closed file.
.
Sim.
def example(path, mode):
with open(path, mode) as f:
return [line for line in f if condition]
..é praticamente equivalente a:
def example(path, mode):
f = open(path, mode)
try:
return [line for line in f if condition]
finally:
f.close()
Mais precisamente, o __exit__
método em um gerenciador de contexto é sempre chamado ao sair do bloco (independentemente de exceções, retornos etc.). O __exit__
método do objeto de arquivo apenas chama f.close()
(por exemplo, aqui no CPython )
finally
keywrod é: def test(): try: return True; finally: return False
.
Sim. De maneira mais geral, o __exit__
método de um Gerenciador de Contexto With Statement será realmente chamado no caso de um return
de dentro do contexto. Isso pode ser testado com o seguinte:
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()
A saída é:
Entering context.
Returning inside with-statement.
EXITING context.
A saída acima confirma que __exit__
foi chamado apesar do início return
. Como tal, o gerenciador de contexto não é ignorado.
Sim, mas pode haver algum efeito colateral em outros casos, porque deve fazer algo (como buffer de liberação) no __exit__
bloco
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
pode ser adicionadowith
para resolver essetry with except
problema. edit: adicionado ao idioma