"contextlib" — "with" 文コンテキスト用ユーティリティ
****************************************************

バージョン 2.5 で追加.

**ソースコード:** Lib/contextlib.py

======================================================================

このモジュールは "with" 文に関わる一般的なタスクのためのユーティリティ
を提供します。詳しい情報は、 コンテキストマネージャ型 と with文とコン
テキストマネージャ を参照してください。

Functions provided:

contextlib.contextmanager(func)

   この関数は "with" 文コンテキストマネージャのファクトリ関数を定義す
   るために利用できる *デコレータ* です。新しいクラスや "__enter__()"
   と "__exit__()" メソッドを別々に定義しなくても、ファクトリ関数を定
   義することができます。

   簡単な例（実際に HTML を生成する方法としてはお勧めできません!）:

      from contextlib import contextmanager

      @contextmanager
      def tag(name):
          print "<%s>" % name
          yield
          print "</%s>" % name

      >>> with tag("h1"):
      ...    print "foo"
      ...
      <h1>
      foo
      </h1>

   デコレート対象の関数は呼び出されたときに *ジェネレータ*-イテレータ
   を返す必要があります。このイテレータは必ず値を1つ yield しなければ
   なりません。 "with" 文の "as" 節が存在するなら、その値は as 節のタ
   ーゲットへ束縛されることになります。

   ジェネレータが yield を実行した箇所で "with" 文のネストされたブロッ
   クが実行されます。ブロックから抜けた後でジェネレータは再開されます
   。ブロック内で処理されない例外が発生した場合は、ジェネレータ内部の
   yield を実行した箇所で例外が再送出されます。なので、(もしあれば) エ
   ラーを捕捉したり、クリーンアップ処理を確実に実行したりするために、
   "try"…"except"…"finally" 構文を使用できます。例外を捕捉する目的が、
   (完全に例外を抑制してしまうのではなく) 単に例外のログをとるため、も
   しくはあるアクションを実行するためなら、ジェネレータはその例外を再
   送出しなければなりません。例外を再送出しない場合、ジェネレータのコ
   ンテキストマネージャは "with" 文に対して例外が処理されたことを示し
   、"with" 文の直後の文から実行を再開します。

contextlib.nested(mgr1[, mgr2[, ...]])

   Combine multiple context managers into a single nested context
   manager.

   This function has been deprecated in favour of the multiple manager
   form of the "with" statement.

   The one advantage of this function over the multiple manager form
   of the "with" statement is that argument unpacking allows it to be
   used with a variable number of context managers as follows:

      from contextlib import nested

      with nested(*managers):
          do_something()

   Note that if the "__exit__()" method of one of the nested context
   managers indicates an exception should be suppressed, no exception
   information will be passed to any remaining outer context managers.
   Similarly, if the "__exit__()" method of one of the nested managers
   raises an exception, any previous exception state will be lost; the
   new exception will be passed to the "__exit__()" methods of any
   remaining outer context managers. In general, "__exit__()" methods
   should avoid raising exceptions, and in particular they should not
   re-raise a passed-in exception.

   This function has two major quirks that have led to it being
   deprecated. Firstly, as the context managers are all constructed
   before the function is invoked, the "__new__()" and "__init__()"
   methods of the inner context managers are not actually covered by
   the scope of the outer context managers. That means, for example,
   that using "nested()" to open two files is a programming error as
   the first file will not be closed promptly if an exception is
   thrown when opening the second file.

   Secondly, if the "__enter__()" method of one of the inner context
   managers raises an exception that is caught and suppressed by the
   "__exit__()" method of one of the outer context managers, this
   construct will raise "RuntimeError" rather than skipping the body
   of the "with" statement.

   Developers that need to support nesting of a variable number of
   context managers can either use the "warnings" module to suppress
   the DeprecationWarning raised by this function or else use this
   function as a model for an application specific implementation.

   バージョン 2.7 で撤廃: The with-statement now supports this
   functionality directly (without the confusing error prone quirks).

contextlib.closing(thing)

   ブロックの完了時に *thing* を close するコンテキストマネージャを返
   します。これは基本的に以下と等価です:

      from contextlib import contextmanager

      @contextmanager
      def closing(thing):
          try:
              yield thing
          finally:
              thing.close()

   そして、明示的に "page" を close する必要なしに、次のように書くこと
   ができます:

      from contextlib import closing
      import urllib

      with closing(urllib.urlopen('http://www.python.org')) as page:
          for line in page:
              print line

   "page" を明示的に close する必要は無く、エラーが発生した場合でも、
   "with" ブロックを出るときに "page.close()" が呼ばれます。

参考:

  **PEP 343** - 「with」 ステートメント
     Python の "with" 文の仕様、背景、および例が記載されています。
