Python の with 文はコンテキストマネージャによって定義される 実行時コンテキストの概念をサポートします。これは、ユーザ定義クラスが文の本体 が実行される前に進入し文の終わりで脱出する実行時コンテキストを定義することを許す 二つの別々のメソッドを使って実装されます。
コンテキスト管理プロトコル (context management protocol) は 実行時コンテキストを定義するコンテキストマネージャオブジェクトが提供すべき 一対のメソッドから成ります。
) |
自分自身を返すコンテキストマネージャの例としてファイルオブジェクトがあります。 ファイルオブジェクトは __enter__() から自分自身を返して open() が with 文のコンテキスト式として使われる ようにします。
関連オブジェクトを返すコンテキストマネージャの例としては
decimal.localcontext()
が返すものがあります。
このマネージャはアクティブな10進数コンテキストをオリジナルのコンテキストのコピーに
セットしてそのコピーを返します。こうすることで、with 文の本体の
内部で、外側のコードに影響を与えずに、10進数コンテキストを変更できます。
exc_type, exc_val, exc_tb) |
このメソッドから真となる値が返されると with 文は例外の発生を抑え、 with 文の直後の文に実行を続けます。そうでなければ、このメソッドの実行を 終えると例外の伝播が続きます。このメソッドの実行中に起きた例外は with 文の本体の実行中に起こった例外を置き換えてしまいます。
渡された例外を直接的に再送出すべきではありません。その代わりに、このメソッドが偽の
値を返すことでメソッドの正常終了と送出された例外を抑制しないことを伝えるべきです。
このようにすれば(contextlib.nested
のような)コンテキストマネージャは
__exit__() メソッド自体が失敗したのかどうかを簡単に見分けることができます。
Python は幾つかのコンテキストマネージャを、易しいスレッド同期・ファイル などのオブジェクトの即時クローズ・単純化されたアクティブな10進算術コン テキストのサポートのために用意しています。各型はコンテキスト管理プロトコル を実装しているという以上の特別の取り扱いを受けるわけではありません。
Python のジェネレータと contextlib.contextfactory
デコレータはこの
プロトコルの簡便な実装方法を提供します。ジェネレータ関数を
contextlib.contextfactory
でデコレートすると、デコレートしなければ
返されるイテレータを返す代わりに、必要な __enter__() および
__exit__() メソッドを実装したコンテキストマネージャを返すようになります。
これらのメソッドのために Python/C API の中の Python オブジェクトの型構 造体に特別なスロットが作られたわけではないことに注意してください。これ らのメソッドを定義したい拡張型については通常の Python からアクセスでき るメソッドとして提供しなければなりません。実行時コンテキストを準備する ことに比べたら、一つのクラスの辞書引きは無視できるオーバーヘッドです。
ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。