In Python, if I return inside a "with" block, will the file still close?
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Digital Sunset Looping
--
Chapters
00:00 In Python, If I Return Inside A &Quot;With&Quot; Block, Will The File Still Close?
00:20 Accepted Answer Score 396
01:02 Answer 2 Score 66
01:39 Answer 3 Score 50
02:25 Answer 4 Score 11
02:56 Thank you
--
Full question
https://stackoverflow.com/questions/9885...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #return #withstatement
#avk47
ACCEPTED ANSWER
Score 408
Yes, it acts like the finally block after a try block, i.e. it always executes (unless the python process terminates in an unusual way of course).
It is also mentioned in one of the examples of PEP-343 which is the specification for the with statement:
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).
Something worth mentioning is however, that you cannot easily catch exceptions thrown by the open() call without putting the whole with block inside a try..except block which is usually not what one wants.
ANSWER 2
Score 69
Yes.
def example(path, mode):
with open(path, mode) as f:
return [line for line in f if condition]
..is pretty much equivalent to:
def example(path, mode):
f = open(path, mode)
try:
return [line for line in f if condition]
finally:
f.close()
More accurately, the __exit__ method in a context manager is always called when exiting the block (regardless of exceptions, returns etc). The file object's __exit__ method just calls f.close() (e.g here in CPython)
ANSWER 3
Score 52
Yes. More generally, the __exit__ method of a With Statement Context Manager will indeed be called in the event of a return from inside the context. This can be tested with the following:
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()
The output is:
Entering context.
Returning inside with-statement.
EXITING context.
The output above confirms that __exit__ was called despite the early return. As such, the context manager is not bypassed.
ANSWER 4
Score 12
Yes, but there may be some side effect in other cases, because it may should do something (like flushing buffer) in __exit__ block
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'