| :mod:`contextlib` --- Utilities for :keyword:`with`\ -statement contexts |
| ======================================================================== |
| |
| .. module:: contextlib |
| :synopsis: Utilities for with-statement contexts. |
| |
| **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: |
| |
| |
| .. decorator:: contextmanager |
| |
| 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. |
| |
| A simple example (this is not recommended as a real way of generating HTML!):: |
| |
| from contextlib import contextmanager |
| |
| @contextmanager |
| def tag(name): |
| print("<%s>" % name) |
| yield |
| print("</%s>" % name) |
| |
| >>> with tag("h1"): |
| ... print("foo") |
| ... |
| <h1> |
| foo |
| </h1> |
| |
| 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. |
| |
| contextmanager uses :class:`ContextDecorator` so the context managers it |
| creates can be used as decorators as well as in :keyword:`with` statements. |
| |
| .. versionchanged:: 3.2 |
| Use of :class:`ContextDecorator`. |
| |
| |
| .. 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 |
| from urllib.request import urlopen |
| |
| with closing(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. |
| |
| |
| .. class:: ContextDecorator() |
| |
| A base class that enables a context manager to also be used as a decorator. |
| |
| Context managers inheriting from ``ContextDecorator`` have to implement |
| ``__enter__`` and ``__exit__`` as normal. ``__exit__`` retains its optional |
| exception handling even when used as a decorator. |
| |
| ``ContextDecorator`` is used by :func:`contextmanager`, so you get this |
| functionality automatically. |
| |
| Example of ``ContextDecorator``:: |
| |
| from contextlib import ContextDecorator |
| |
| class mycontext(ContextDecorator): |
| def __enter__(self): |
| print('Starting') |
| return self |
| |
| def __exit__(self, *exc): |
| print('Finishing') |
| return False |
| |
| >>> @mycontext() |
| ... def function(): |
| ... print('The bit in the middle') |
| ... |
| >>> function() |
| Starting |
| The bit in the middle |
| Finishing |
| |
| >>> with mycontext(): |
| ... print('The bit in the middle') |
| ... |
| Starting |
| The bit in the middle |
| Finishing |
| |
| This change is just syntactic sugar for any construct of the following form:: |
| |
| def f(): |
| with cm(): |
| # Do stuff |
| |
| ``ContextDecorator`` lets you instead write:: |
| |
| @cm() |
| def f(): |
| # Do stuff |
| |
| It makes it clear that the ``cm`` applies to the whole function, rather than |
| just a piece of it (and saving an indentation level is nice, too). |
| |
| Existing context managers that already have a base class can be extended by |
| using ``ContextDecorator`` as a mixin class:: |
| |
| from contextlib import ContextDecorator |
| |
| class mycontext(ContextBaseClass, ContextDecorator): |
| def __enter__(self): |
| return self |
| |
| def __exit__(self, *exc): |
| return False |
| |
| .. versionadded:: 3.2 |
| |
| |
| .. seealso:: |
| |
| :pep:`0343` - The "with" statement |
| The specification, background, and examples for the Python :keyword:`with` |
| statement. |
| |