5

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が、閉じると基になるストリームも閉じられることがわかりました...)

4

1 に答える 1

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()
于 2013-07-05T13:20:03.367 に答える