我有一个对象,我希望能够使用with
关键字。我对实施情境管理人员的实际情况感到满意,但我正面对最佳实践问题。
该对象是文件的包装器。我计划用一个字符串(文件的路径)或者像文件一样初始化我的对象,这可以直接处理(文件里面有文件的可能性 - 所以我预见到一个明确的用例这与BytesIO等...)
所以__init__
看起来像这样:
def __init__(self, file_to_process):
if isinstance(file_to_process, str):
self._underlying_stream = open(file_to_process, "rb") # it's the path to a file
elif isinstance(file_to_process, io.IOBase):
self._underlying_stream = file_to_process # its the file itself
else:
raise TypeError()
所以我的问题是,在_underlying_stream
函数中关闭__exit__()
是最佳做法/接受/明智吗?当它成为一条道路时,它完全有道理,但如果它是一条流进来的话,它最让我感到不礼貌,最坏的情况是危险关闭self._underlying_stream
- 我认为是正确的,如果所以,有一个巧妙的方法吗?
(注意:我考虑使用io.BufferedReader
来包装流,但事实证明关闭它也会关闭基础流......)
答案 0 :(得分:6)
我不关闭基础流。传入已经打开的文件对象意味着调用者已经对该对象负责,并且在__exit__
上关闭该对象将是非常烦人的。
PIL做了类似的事情,尽管不是在上下文管理器中。传入文件名时,它会在完成读取图像数据后关闭文件对象。它为此设置了一个布尔标志。传入一个文件对象,它会读取但不会关闭。
我也会这样做:
class Foo(object):
_close_on_exit = False
def __init__(self, file_to_process):
if isinstance(file_to_process, str):
self._underlying_stream = open(file_to_process, "rb") # it's the path to a file
self._close_on_exit = True
elif isinstance(file_to_process, io.IOBase):
self._underlying_stream = file_to_process # its the file itself
else:
raise TypeError()
def __exit__(self, exc_type, exc_value, traceback):
if self._close_on_exit:
self._underlying_stream.close()