You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
5.9 KiB
148 lines
5.9 KiB
:mod:`contextlib` --- Utilities for :keyword:`with`\ -statement contexts
|
|
========================================================================
|
|
|
|
.. module:: contextlib
|
|
:synopsis: Utilities for with-statement contexts.
|
|
|
|
|
|
.. versionadded:: 2.5
|
|
|
|
**Source code:** :source:`Lib/contextlib.py`
|
|
|
|
--------------
|
|
|
|
This module provides utilities for common tasks involving the :keyword:`with`
|
|
statement. For more information see also :ref:`typecontextmanager` and
|
|
:ref:`context-managers`.
|
|
|
|
Functions provided:
|
|
|
|
|
|
.. function:: contextmanager(func)
|
|
|
|
This function is a :term:`decorator` that can be used to define a factory
|
|
function for :keyword:`with` statement context managers, without needing to
|
|
create a class or separate :meth:`__enter__` and :meth:`__exit__` methods.
|
|
|
|
While many objects natively support use in with statements, sometimes a
|
|
resource needs to be managed that isn't a context manager in its own right,
|
|
and doesn't implement a ``close()`` method for use with ``contextlib.closing``
|
|
|
|
An abstract example would be the following to ensure correct resource
|
|
management::
|
|
|
|
from contextlib import contextmanager
|
|
|
|
@contextmanager
|
|
def managed_resource(*args, **kwds):
|
|
# Code to acquire resource, e.g.:
|
|
resource = acquire_resource(*args, **kwds)
|
|
try:
|
|
yield resource
|
|
finally:
|
|
# Code to release resource, e.g.:
|
|
release_resource(resource)
|
|
|
|
>>> with managed_resource(timeout=3600) as resource:
|
|
... # Resource is released at the end of this block,
|
|
... # even if code in the block raises an exception
|
|
|
|
The function being decorated must return a :term:`generator`-iterator when
|
|
called. This iterator must yield exactly one value, which will be bound to
|
|
the targets in the :keyword:`with` statement's :keyword:`as` clause, if any.
|
|
|
|
At the point where the generator yields, the block nested in the :keyword:`with`
|
|
statement is executed. The generator is then resumed after the block is exited.
|
|
If an unhandled exception occurs in the block, it is reraised inside the
|
|
generator at the point where the yield occurred. Thus, you can use a
|
|
:keyword:`try`...\ :keyword:`except`...\ :keyword:`finally` statement to trap
|
|
the error (if any), or ensure that some cleanup takes place. If an exception is
|
|
trapped merely in order to log it or to perform some action (rather than to
|
|
suppress it entirely), the generator must reraise that exception. Otherwise the
|
|
generator context manager will indicate to the :keyword:`with` statement that
|
|
the exception has been handled, and execution will resume with the statement
|
|
immediately following the :keyword:`with` statement.
|
|
|
|
|
|
.. function:: 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 :keyword:`with` statement.
|
|
|
|
The one advantage of this function over the multiple manager form of the
|
|
:keyword:`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 :meth:`__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
|
|
:meth:`__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
|
|
:meth:`__exit__` methods of any remaining outer context managers. In general,
|
|
:meth:`__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
|
|
:meth:`__new__` and :meth:`__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 :func:`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 :meth:`__enter__` method of one of the inner context managers
|
|
raises an exception that is caught and suppressed by the :meth:`__exit__` method
|
|
of one of the outer context managers, this construct will raise
|
|
:exc:`RuntimeError` rather than skipping the body of the :keyword:`with`
|
|
statement.
|
|
|
|
Developers that need to support nesting of a variable number of context managers
|
|
can either use the :mod:`warnings` module to suppress the DeprecationWarning
|
|
raised by this function or else use this function as a model for an application
|
|
specific implementation.
|
|
|
|
.. deprecated:: 2.7
|
|
The with-statement now supports this functionality directly (without the
|
|
confusing error prone quirks).
|
|
|
|
.. function:: closing(thing)
|
|
|
|
Return a context manager that closes *thing* upon completion of the block. This
|
|
is basically equivalent to::
|
|
|
|
from contextlib import contextmanager
|
|
|
|
@contextmanager
|
|
def closing(thing):
|
|
try:
|
|
yield thing
|
|
finally:
|
|
thing.close()
|
|
|
|
And lets you write code like this::
|
|
|
|
from contextlib import closing
|
|
import urllib
|
|
|
|
with closing(urllib.urlopen('http://www.python.org')) as page:
|
|
for line in page:
|
|
print line
|
|
|
|
without needing to explicitly close ``page``. Even if an error occurs,
|
|
``page.close()`` will be called when the :keyword:`with` block is exited.
|
|
|
|
|
|
.. seealso::
|
|
|
|
:pep:`343` - The "with" statement
|
|
The specification, background, and examples for the Python :keyword:`with`
|
|
statement.
|
|
|