#
10 コンテキストマネージャ型

バージョン 2.5 で 新たに追加 された仕様です。

Python の `with` 文はコンテキストマネージャによって定義される 実行時コンテキストの概念をサポートします。これは、ユーザ定義クラスが文の本体 が実行される前に進入し文の終わりで脱出する実行時コンテキストを定義することを許す 二つの別々のメソッドを使って実装されます。

コンテキスト管理プロトコル (context management protocol) は 実行時コンテキストを定義するコンテキストマネージャオブジェクトが提供すべき 一対のメソッドから成ります。

`__enter__`( | )

  実行時コンテキストに入り、このオブジェクトまたは他の実行時コンテキストに関連した オブジェクトを返します。このメソッドが返す値はこのコンテキストマネージャを使う `with` 文の `as` 節の識別子に束縛されます。

  自分自身を返すコンテキストマネージャの例としてファイルオブジェクトがあります。 ファイルオブジェクトは `__enter__()` から自分自身を返して `open()` が `with` 文のコンテキスト式として使われる ようにします。

  関連オブジェクトを返すコンテキストマネージャの例としては `decimal.localcontext()` が返すものがあります。 このマネージャはアクティブな10進数コンテキストをオリジナルのコンテキストのコピーに セットしてそのコピーを返します。こうすることで、`with` 文の本体の 内部で、外側のコードに影響を与えずに、10進数コンテキストを変更できます。

`__exit__`( | exc_type, exc_val, exc_tb)

  実行時コンテキストから抜け、例外(がもし起こっていたとしても)を抑制することを示す ブール値フラグを返します。`with` 文の本体を実行中に例外が起こったならば、引数には その例外の型と値とトレースバック情報を渡します。そうでなければ、引数は全て None です。

  このメソッドから真となる値が返されると `with` 文は例外の発生を抑え、 `with` 文の直後の文に実行を続けます。そうでなければ、このメソッドの実行を 終えると例外の伝播が続きます。このメソッドの実行中に起きた例外は `with` 文の本体の実行中に起こった例外を置き換えてしまいます。

  渡された例外を直接的に再送出すべきではありません。その代わりに、このメソッドが偽の 値を返すことでメソッドの正常終了と送出された例外を抑制しないことを伝えるべきです。 このようにすれば(`contextlib.nested` のような)コンテキストマネージャは `__exit__()` メソッド自体が失敗したのかどうかを簡単に見分けることができます。

Python は幾つかのコンテキストマネージャを、易しいスレッド同期・ファイル などのオブジェクトの即時クローズ・単純化されたアクティブな10進算術コン テキストのサポートのために用意しています。各型はコンテキスト管理プロトコル を実装しているという以上の特別の取り扱いを受けるわけではありません。

Python のジェネレータと `contextlib.contextfactory` デコレータはこの プロトコルの簡便な実装方法を提供します。ジェネレータ関数を `contextlib.contextfactory` でデコレートすると、デコレートしなければ 返されるイテレータを返す代わりに、必要な `__enter__()` および `__exit__()` メソッドを実装したコンテキストマネージャを返すようになります。

これらのメソッドのために Python/C API の中の Python オブジェクトの型構 造体に特別なスロットが作られたわけではないことに注意してください。これ らのメソッドを定義したい拡張型については通常の Python からアクセスでき るメソッドとして提供しなければなりません。実行時コンテキストを準備する ことに比べたら、一つのクラスの辞書引きは無視できるオーバーヘッドです。