[2] | 1 | :mod:`contextlib` --- Utilities for :keyword:`with`\ -statement contexts
|
---|
| 2 | ========================================================================
|
---|
| 3 |
|
---|
| 4 | .. module:: contextlib
|
---|
| 5 | :synopsis: Utilities for with-statement contexts.
|
---|
| 6 |
|
---|
| 7 |
|
---|
| 8 | .. versionadded:: 2.5
|
---|
| 9 |
|
---|
[391] | 10 | **Source code:** :source:`Lib/contextlib.py`
|
---|
| 11 |
|
---|
| 12 | --------------
|
---|
| 13 |
|
---|
[2] | 14 | This module provides utilities for common tasks involving the :keyword:`with`
|
---|
| 15 | statement. For more information see also :ref:`typecontextmanager` and
|
---|
| 16 | :ref:`context-managers`.
|
---|
| 17 |
|
---|
| 18 | Functions provided:
|
---|
| 19 |
|
---|
| 20 |
|
---|
| 21 | .. function:: contextmanager(func)
|
---|
| 22 |
|
---|
| 23 | This function is a :term:`decorator` that can be used to define a factory
|
---|
| 24 | function for :keyword:`with` statement context managers, without needing to
|
---|
| 25 | create a class or separate :meth:`__enter__` and :meth:`__exit__` methods.
|
---|
| 26 |
|
---|
| 27 | A simple example (this is not recommended as a real way of generating HTML!)::
|
---|
| 28 |
|
---|
| 29 | from contextlib import contextmanager
|
---|
| 30 |
|
---|
| 31 | @contextmanager
|
---|
| 32 | def tag(name):
|
---|
| 33 | print "<%s>" % name
|
---|
| 34 | yield
|
---|
| 35 | print "</%s>" % name
|
---|
| 36 |
|
---|
| 37 | >>> with tag("h1"):
|
---|
| 38 | ... print "foo"
|
---|
| 39 | ...
|
---|
| 40 | <h1>
|
---|
| 41 | foo
|
---|
| 42 | </h1>
|
---|
| 43 |
|
---|
| 44 | The function being decorated must return a :term:`generator`-iterator when
|
---|
| 45 | called. This iterator must yield exactly one value, which will be bound to
|
---|
| 46 | the targets in the :keyword:`with` statement's :keyword:`as` clause, if any.
|
---|
| 47 |
|
---|
| 48 | At the point where the generator yields, the block nested in the :keyword:`with`
|
---|
| 49 | statement is executed. The generator is then resumed after the block is exited.
|
---|
| 50 | If an unhandled exception occurs in the block, it is reraised inside the
|
---|
| 51 | generator at the point where the yield occurred. Thus, you can use a
|
---|
| 52 | :keyword:`try`...\ :keyword:`except`...\ :keyword:`finally` statement to trap
|
---|
| 53 | the error (if any), or ensure that some cleanup takes place. If an exception is
|
---|
| 54 | trapped merely in order to log it or to perform some action (rather than to
|
---|
| 55 | suppress it entirely), the generator must reraise that exception. Otherwise the
|
---|
| 56 | generator context manager will indicate to the :keyword:`with` statement that
|
---|
| 57 | the exception has been handled, and execution will resume with the statement
|
---|
| 58 | immediately following the :keyword:`with` statement.
|
---|
| 59 |
|
---|
| 60 |
|
---|
| 61 | .. function:: nested(mgr1[, mgr2[, ...]])
|
---|
| 62 |
|
---|
| 63 | Combine multiple context managers into a single nested context manager.
|
---|
| 64 |
|
---|
[391] | 65 | This function has been deprecated in favour of the multiple manager form
|
---|
| 66 | of the :keyword:`with` statement.
|
---|
[2] | 67 |
|
---|
[391] | 68 | The one advantage of this function over the multiple manager form of the
|
---|
| 69 | :keyword:`with` statement is that argument unpacking allows it to be
|
---|
| 70 | used with a variable number of context managers as follows::
|
---|
| 71 |
|
---|
[2] | 72 | from contextlib import nested
|
---|
| 73 |
|
---|
[391] | 74 | with nested(*managers):
|
---|
[2] | 75 | do_something()
|
---|
| 76 |
|
---|
| 77 | Note that if the :meth:`__exit__` method of one of the nested context managers
|
---|
| 78 | indicates an exception should be suppressed, no exception information will be
|
---|
| 79 | passed to any remaining outer context managers. Similarly, if the
|
---|
| 80 | :meth:`__exit__` method of one of the nested managers raises an exception, any
|
---|
| 81 | previous exception state will be lost; the new exception will be passed to the
|
---|
| 82 | :meth:`__exit__` methods of any remaining outer context managers. In general,
|
---|
| 83 | :meth:`__exit__` methods should avoid raising exceptions, and in particular they
|
---|
| 84 | should not re-raise a passed-in exception.
|
---|
| 85 |
|
---|
[391] | 86 | This function has two major quirks that have led to it being deprecated. Firstly,
|
---|
| 87 | as the context managers are all constructed before the function is invoked, the
|
---|
| 88 | :meth:`__new__` and :meth:`__init__` methods of the inner context managers are
|
---|
| 89 | not actually covered by the scope of the outer context managers. That means, for
|
---|
| 90 | example, that using :func:`nested` to open two files is a programming error as the
|
---|
| 91 | first file will not be closed promptly if an exception is thrown when opening
|
---|
| 92 | the second file.
|
---|
[2] | 93 |
|
---|
[391] | 94 | Secondly, if the :meth:`__enter__` method of one of the inner context managers
|
---|
| 95 | raises an exception that is caught and suppressed by the :meth:`__exit__` method
|
---|
| 96 | of one of the outer context managers, this construct will raise
|
---|
| 97 | :exc:`RuntimeError` rather than skipping the body of the :keyword:`with`
|
---|
| 98 | statement.
|
---|
| 99 |
|
---|
| 100 | Developers that need to support nesting of a variable number of context managers
|
---|
| 101 | can either use the :mod:`warnings` module to suppress the DeprecationWarning
|
---|
| 102 | raised by this function or else use this function as a model for an application
|
---|
| 103 | specific implementation.
|
---|
| 104 |
|
---|
| 105 | .. deprecated:: 2.7
|
---|
| 106 | The with-statement now supports this functionality directly (without the
|
---|
| 107 | confusing error prone quirks).
|
---|
| 108 |
|
---|
[2] | 109 | .. function:: closing(thing)
|
---|
| 110 |
|
---|
| 111 | Return a context manager that closes *thing* upon completion of the block. This
|
---|
| 112 | is basically equivalent to::
|
---|
| 113 |
|
---|
| 114 | from contextlib import contextmanager
|
---|
| 115 |
|
---|
| 116 | @contextmanager
|
---|
| 117 | def closing(thing):
|
---|
| 118 | try:
|
---|
| 119 | yield thing
|
---|
| 120 | finally:
|
---|
| 121 | thing.close()
|
---|
| 122 |
|
---|
| 123 | And lets you write code like this::
|
---|
| 124 |
|
---|
| 125 | from contextlib import closing
|
---|
| 126 | import urllib
|
---|
| 127 |
|
---|
| 128 | with closing(urllib.urlopen('http://www.python.org')) as page:
|
---|
| 129 | for line in page:
|
---|
| 130 | print line
|
---|
| 131 |
|
---|
| 132 | without needing to explicitly close ``page``. Even if an error occurs,
|
---|
| 133 | ``page.close()`` will be called when the :keyword:`with` block is exited.
|
---|
| 134 |
|
---|
| 135 |
|
---|
| 136 | .. seealso::
|
---|
| 137 |
|
---|
| 138 | :pep:`0343` - The "with" statement
|
---|
| 139 | The specification, background, and examples for the Python :keyword:`with`
|
---|
| 140 | statement.
|
---|
| 141 |
|
---|