我应该在上下文管理器__exit __()函数中关闭传递给我的对象的流(类文件对象)吗?

Lex*_*ust 5 python file stream contextmanager

我有一个对象,我希望能够使用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()
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,_underlying_stream在我的__exit__()功能中关闭它是最好的做法/接受/明智吗?当它成为一条小路时,它完全有道理,但如果它是一条小溪传入,它最让我感到不礼貌,最坏的情况是关闭self._underlying_stream- 我是否正确思考,如果是这样,是否有一个整洁的方式这个?

(注意:我考虑用a来包装流io.BufferedReader,但事实证明,关闭也将关闭底层流...)

Mar*_*ers 7

不会关闭底层流.传入已经打开的文件对象意味着调用者已经对该对象负责并且关闭该对象__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()
Run Code Online (Sandbox Code Playgroud)