blob: 5e1a11a11649eefc05bb02be2216505a767847c1 [file] [log] [blame]
Georg Brandl0eaab972009-06-08 08:00:22 +00001:mod:`contextlib` --- Utilities for :keyword:`with`\ -statement contexts
2========================================================================
Georg Brandl116aa622007-08-15 14:28:22 +00003
4.. module:: contextlib
5 :synopsis: Utilities for with-statement contexts.
6
7
Georg Brandl116aa622007-08-15 14:28:22 +00008This module provides utilities for common tasks involving the :keyword:`with`
9statement. For more information see also :ref:`typecontextmanager` and
10:ref:`context-managers`.
11
Éric Araujo6e6cb8e2010-11-16 19:13:50 +000012.. seealso::
13
14 Latest version of the :source:`contextlib Python source code
15 <Lib/contextlib.py>`
16
Georg Brandl116aa622007-08-15 14:28:22 +000017Functions provided:
18
19
Georg Brandl8a1caa22010-07-29 16:01:11 +000020.. decorator:: contextmanager
Georg Brandl116aa622007-08-15 14:28:22 +000021
Christian Heimesd8654cf2007-12-02 15:22:16 +000022 This function is a :term:`decorator` that can be used to define a factory
23 function for :keyword:`with` statement context managers, without needing to
24 create a class or separate :meth:`__enter__` and :meth:`__exit__` methods.
Georg Brandl116aa622007-08-15 14:28:22 +000025
26 A simple example (this is not recommended as a real way of generating HTML!)::
27
Georg Brandl116aa622007-08-15 14:28:22 +000028 from contextlib import contextmanager
29
30 @contextmanager
31 def tag(name):
Georg Brandl6911e3c2007-09-04 07:15:32 +000032 print("<%s>" % name)
Georg Brandl116aa622007-08-15 14:28:22 +000033 yield
Georg Brandl6911e3c2007-09-04 07:15:32 +000034 print("</%s>" % name)
Georg Brandl116aa622007-08-15 14:28:22 +000035
36 >>> with tag("h1"):
Georg Brandl6911e3c2007-09-04 07:15:32 +000037 ... print("foo")
Georg Brandl116aa622007-08-15 14:28:22 +000038 ...
39 <h1>
40 foo
41 </h1>
42
Georg Brandl9afde1c2007-11-01 20:32:30 +000043 The function being decorated must return a :term:`generator`-iterator when
44 called. This iterator must yield exactly one value, which will be bound to
45 the targets in the :keyword:`with` statement's :keyword:`as` clause, if any.
Georg Brandl116aa622007-08-15 14:28:22 +000046
47 At the point where the generator yields, the block nested in the :keyword:`with`
48 statement is executed. The generator is then resumed after the block is exited.
49 If an unhandled exception occurs in the block, it is reraised inside the
50 generator at the point where the yield occurred. Thus, you can use a
51 :keyword:`try`...\ :keyword:`except`...\ :keyword:`finally` statement to trap
52 the error (if any), or ensure that some cleanup takes place. If an exception is
53 trapped merely in order to log it or to perform some action (rather than to
54 suppress it entirely), the generator must reraise that exception. Otherwise the
55 generator context manager will indicate to the :keyword:`with` statement that
56 the exception has been handled, and execution will resume with the statement
57 immediately following the :keyword:`with` statement.
58
Michael Foordb3a89842010-06-30 12:17:50 +000059 contextmanager uses :class:`ContextDecorator` so the context managers it
60 creates can be used as decorators as well as in :keyword:`with` statements.
61
62 .. versionchanged:: 3.2
63 Use of :class:`ContextDecorator`.
Georg Brandl116aa622007-08-15 14:28:22 +000064
Georg Brandl86e78d12010-07-18 13:43:32 +000065
Georg Brandl116aa622007-08-15 14:28:22 +000066.. function:: closing(thing)
67
68 Return a context manager that closes *thing* upon completion of the block. This
69 is basically equivalent to::
70
71 from contextlib import contextmanager
72
73 @contextmanager
74 def closing(thing):
75 try:
76 yield thing
77 finally:
78 thing.close()
79
80 And lets you write code like this::
81
Georg Brandl116aa622007-08-15 14:28:22 +000082 from contextlib import closing
Georg Brandl0f7ede42008-06-23 11:23:31 +000083 from urllib.request import urlopen
Georg Brandl116aa622007-08-15 14:28:22 +000084
Georg Brandl0f7ede42008-06-23 11:23:31 +000085 with closing(urlopen('http://www.python.org')) as page:
Georg Brandl116aa622007-08-15 14:28:22 +000086 for line in page:
Georg Brandl6911e3c2007-09-04 07:15:32 +000087 print(line)
Georg Brandl116aa622007-08-15 14:28:22 +000088
89 without needing to explicitly close ``page``. Even if an error occurs,
90 ``page.close()`` will be called when the :keyword:`with` block is exited.
91
92
Michael Foordb3a89842010-06-30 12:17:50 +000093.. class:: ContextDecorator()
94
95 A base class that enables a context manager to also be used as a decorator.
96
97 Context managers inheriting from ``ContextDecorator`` have to implement
98 ``__enter__`` and ``__exit__`` as normal. ``__exit__`` retains its optional
99 exception handling even when used as a decorator.
100
Georg Brandl86e78d12010-07-18 13:43:32 +0000101 ``ContextDecorator`` is used by :func:`contextmanager`, so you get this
102 functionality automatically.
103
104 Example of ``ContextDecorator``::
Michael Foordb3a89842010-06-30 12:17:50 +0000105
106 from contextlib import ContextDecorator
107
108 class mycontext(ContextDecorator):
Georg Brandl86e78d12010-07-18 13:43:32 +0000109 def __enter__(self):
110 print('Starting')
111 return self
Michael Foordb3a89842010-06-30 12:17:50 +0000112
Georg Brandl86e78d12010-07-18 13:43:32 +0000113 def __exit__(self, *exc):
114 print('Finishing')
115 return False
Michael Foordb3a89842010-06-30 12:17:50 +0000116
117 >>> @mycontext()
118 ... def function():
Georg Brandl86e78d12010-07-18 13:43:32 +0000119 ... print('The bit in the middle')
Michael Foordb3a89842010-06-30 12:17:50 +0000120 ...
121 >>> function()
122 Starting
123 The bit in the middle
124 Finishing
125
126 >>> with mycontext():
Georg Brandl86e78d12010-07-18 13:43:32 +0000127 ... print('The bit in the middle')
Michael Foordb3a89842010-06-30 12:17:50 +0000128 ...
129 Starting
130 The bit in the middle
131 Finishing
132
Georg Brandl86e78d12010-07-18 13:43:32 +0000133 This change is just syntactic sugar for any construct of the following form::
134
135 def f():
136 with cm():
137 # Do stuff
138
139 ``ContextDecorator`` lets you instead write::
140
141 @cm()
142 def f():
143 # Do stuff
144
145 It makes it clear that the ``cm`` applies to the whole function, rather than
146 just a piece of it (and saving an indentation level is nice, too).
147
Michael Foordb3a89842010-06-30 12:17:50 +0000148 Existing context managers that already have a base class can be extended by
149 using ``ContextDecorator`` as a mixin class::
150
151 from contextlib import ContextDecorator
152
153 class mycontext(ContextBaseClass, ContextDecorator):
Georg Brandl86e78d12010-07-18 13:43:32 +0000154 def __enter__(self):
155 return self
Michael Foordb3a89842010-06-30 12:17:50 +0000156
Georg Brandl86e78d12010-07-18 13:43:32 +0000157 def __exit__(self, *exc):
158 return False
Michael Foordb3a89842010-06-30 12:17:50 +0000159
160 .. versionadded:: 3.2
161
162
Georg Brandl116aa622007-08-15 14:28:22 +0000163.. seealso::
164
165 :pep:`0343` - The "with" statement
166 The specification, background, and examples for the Python :keyword:`with`
167 statement.
168