コンテキストマネージャーとwith文 Pythonトリックより

with文

Pythonに限らずファイルをオープンしたらクローズしないといけない。

with文がなかったころは、こう書いていた。

f = open('hello.txt', 'w')
try:
    f.write('hello, world')
finally:
    f.cloe()

with分を使うとこう書ける。

with open('hello.txt', 'w') as f:
    f.write('hello, world')

enterexit

自作したクラスでもwith文に沿ってopen->closeができる。それがコンテキストマネージャー

以下のようにクラスに__enter____exit__を実装してあげればよいとのこと。

3. Data model — Python 3.8.2 documentation

class ManagedFile:
    def __init__(self, name):
        self.name = name
    
    def __enter__(self):
        self.file = open(self.name, 'w')

    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.file:
            self.file.close()

コンテキストマネージャー

クラスだけではなくcontextmanagerデコレータを使用することで、関数に対してwith文を適用できる。

from contextlib import contextmanager

@contextmanager
def managed_file(name):
    try:
        f = open(name, 'w')
        yield f
    finally:
        f.close()

with managed_file('hello.txt') as f:
    f.write('hello, world!')
    f.write('bye now')

大昔ですがJavaもtry-catchのtryでcloseできるようになりましたよね。 一瞬で実行し終えるスクリプトならcloseが漏れても、プロセスが終了するので問題ないが バッチ処理とか長時間処理する場合は、クローズ漏れはリソースを逼迫します。 コンテキストマネージャとwith文積極利用していきましょう。