Say I have a function that returns a context-managed object, here a tempfile.TemporaryFile
:
import tempfile
def make_temp_file():
"""Create a temporary file. Best used with a context manager"""
tmpfile = tempfile.NamedTemporaryFile()
return tmpfile
Is this safe as is or should this be wrapped with a context manager?
import tempfile
from contextlib import contextmanager
@contextmanager
def make_temp_file():
"""Create a temporary file. Best used with a context manager"""
tmpfile = tempfile.NamedTemporaryFile()
return tmpfile
My confusion comes from the linter pylint who still insist the first example triggers a consider-using-with
rule.
Your function already returns a context object (something with __enter__
and __exit__
methods) and does not need to be rewrapped. That wouldn't change anything.
The idea of with
is that the context manager's __exit__
will be called when the with
suite finishes, even if there is an error. But algorithms don't always fit conveniently into suites as your code indicates. If you can't use a context manager, you need some other mechanism to ensure that something closes the object.
As an example, suppose your function performed some other task before return
. It could hit an exception and terminate before anybody has a chance to close the object. In that case you would do
def make_temp_file():
tmpfile = tempfile.NamedTemporaryFile()
try:
do_other_things()
except:
tmpfile.close()
raise
If your function doesn't do anything after creating the object, you can skip the intermediate variable and likely get rid of the lint warning while you are at it. From the pylint doc the warning is suppressed when the call result is returned from the enclosing function.
def make_temp_file():
return tempfile.NamedTemporaryFile()
Note that since you return a context object that needs to be closed, the same issues apply to the thing that calls the function. Either that should be a with
or should have some other mechanism to make sure the object is closed when done.