Учтите следующее:
with open(path, mode) as f:
return [line for line in f if condition]
Будет ли файл закрыт должным образом, или использование return
каким- либо образом обходить менеджер контекста ?
Учтите следующее:
with open(path, mode) as f:
return [line for line in f if condition]
Будет ли файл закрыт должным образом, или использование return
каким- либо образом обходить менеджер контекста ?
Ответы:
Да, он действует как finally
блок после try
блока, то есть он всегда выполняется (если, конечно, процесс python не завершается необычным образом).
Это также упоминается в одном из примеров PEP-343, который является спецификацией для 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).
Однако стоит упомянуть, что вы не можете легко перехватывать исключения, генерируемые open()
вызовом, не помещая весь with
блок в try..except
блок, который обычно не соответствует желаемому.
Process.terminate()
это один из немногих (единственный?) Сценарий, который не гарантирует вызова finally
оператора: «Обратите внимание, что обработчики выхода и предложения finally и т. Д. Не будут казнены «.
with
блока, гарантия будет действительна до тех пор, пока генератор продолжает давать значения? до тех пор, пока что-нибудь ссылается на это? Т.е. мне нужно использовать del
или присвоить другое значение переменной, которая содержит объект генератора?
ValueError: I/O operation on closed file.
.
Да.
def example(path, mode):
with open(path, mode) as f:
return [line for line in f if condition]
..это в значительной степени эквивалентно:
def example(path, mode):
f = open(path, mode)
try:
return [line for line in f if condition]
finally:
f.close()
Точнее, __exit__
метод в диспетчере контекста всегда вызывается при выходе из блока (независимо от исключений, возвратов и т. Д.). Метод файлового объекта __exit__
просто вызывает f.close()
(например, здесь, в CPython )
finally
keywrod является: def test(): try: return True; finally: return False
.
Да. В более общем смысле __exit__
метод диспетчера контекста With Statement действительно вызывается в случае, если return
внутри контекста. Это можно проверить с помощью следующего:
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()
Выход:
Entering context.
Returning inside with-statement.
EXITING context.
Вывод выше подтверждает, что __exit__
звонили несмотря на раннее return
. Таким образом, менеджер контекста не обойден.
Да, но в других случаях может быть некоторый побочный эффект, потому что он может что-то делать (например, очищать буфер) в __exit__
блоке
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
можно было бы добавить,with
чтобы решить этуtry with except
проблему. Редактировать: добавлено в язык