2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Python contextlib.ExitStackで複数のコンテキストマネージャをまとめて管理する

Last updated at Posted at 2020-09-05

Python標準ライブラリのcontextlib.ExitStackクラスを使うと複数のコンテキストマネージャ1をまとめて管理できます。ExitStackクラスのメリットを以下に列挙します。

  • ExitStackクラスもコンテキストマネージャなのでwith文でスコープを指定できる。
  • クラスのインスタンス変数に含まれるコンテキストマネージャを__init__メソッドで登録してまとめて管理できる。
  • pushメソッドとenter_contextメソッドの使い分けで__enter__メソッドの呼び出しを制御できる。

pushメソッドとenter_contextメソッドの動作確認

pushメソッドは管理対象の__enter__メソッドを呼び出さず、enter_contextメソッドは管理対象の__enter__メソッドを呼び出します。通常はenter_contextメソッドを使用すれば問題ありません。

from contextlib import ExitStack


class TestClass:
    def __init__(self):
        print("TestClass.__init__()")

    def __enter__(self):
        print("TestClass.__enter__()")
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print("TestClass.__exit__()")


with ExitStack() as stack:
    stack.push(TestClass())
    # TestClass.__init__()
    # TestClass.__exit__()

with ExitStack() as stack:
    stack.enter_context(TestClass())
    # TestClass.__init__()
    # TestClass.__enter__()
    # TestClass.__exit__()

実用例:ディレクトリ中のファイルをopen組み込み関数でまとめて開いてExitStackで管理する。

ハンドルリソース管理の問題から多用することはありませんが、ExitStackwith文を組み合わせることでディレクトリ中のファイルをまとめて開いて管理できます。

import os
from contextlib import ExitStack
from typing import List, BinaryIO

# ExitStackオブジェクトをwith文で作成・開始する。
with ExitStack() as stack:
    # カレントディレクトリ中のファイルのパスを取得する。
    # open組み込み関数が失敗するのでディレクトリは除外する。
    paths: List[str] = [path for path in os.listdir(".") if os.path.isfile(path)]

    # ファイルをExitStackに追加しながら開く。
    files: List[BinaryIO] = [stack.enter_context(open(path, "rb")) for path in paths]

    # 開いたファイルを適当に処理する。
    file: BinaryIO
    for file in files:
        print(",".join([hex(byte).ljust(2, "0") for byte in file.read(5)]))

# ExitStackオブジェクト(stack)に登録されたコンテキストマネージャは
# with文の終了時点で解放される。

関連情報

  1. コンテキストマネージャ:__enter__メソッドと__exit__メソッドを実装したオブジェクト。参考:公式ドキュメント

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?