返回上下文管理对象的函数是否需用@contextmanager装饰?
问题解答
第一种写法是否安全?
完全安全。tempfile.NamedTemporaryFile实例本身就实现了上下文管理器协议(自带__enter__和__exit__方法),你的函数只是创建并返回这个实例,只要调用时用with语句包裹,就能正常触发资源清理:
with make_temp_file() as f: # 操作临时文件 f.write(b"test content") f.seek(0) print(f.read())
临时文件会在with块结束后自动关闭,系统默认逻辑下的删除操作也会正常执行(Windows下关闭即删除,Linux下上下文管理器会处理对应清理)。
第二种写法有什么问题?
你当前写的带@contextmanager的版本是错误的,会直接抛出异常。因为@contextmanager要求装饰的是生成器函数,必须用yield而非return来返回上下文对象。如果一定要用装饰器,正确写法应该是:
import tempfile from contextlib import contextmanager @contextmanager def make_temp_file(): """Create a temporary file. Best used with a context manager""" tmpfile = tempfile.NamedTemporaryFile() try: yield tmpfile finally: tmpfile.close() # 其实NamedTemporaryFile的__exit__已自带此逻辑,显式书写仅作补充
但这种写法其实没必要,因为NamedTemporaryFile本身就是合法的上下文管理器,属于多此一举的包装。
为什么pylint触发consider-using-with规则?
这是pylint的误报。它检测到你在函数内部直接创建了NamedTemporaryFile实例却没有立刻用with包裹,就触发了规则,但实际上你是把实例返回给调用方去用with处理。你可以通过添加注释忽略这个误报:
import tempfile def make_temp_file(): """Create a temporary file. Best used with a context manager""" tmpfile = tempfile.NamedTemporaryFile() # pylint: disable=consider-using-with return tmpfile
内容的提问来源于stack exchange,提问作者Keto
相关产品推荐
相关产品推荐

