blob: 35eb882f66319d8f8ecf26c2ec5a0c317e03b2eb [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
12Functions provided:
13
14
Georg Brandl8a1caa22010-07-29 16:01:11 +000015.. decorator:: contextmanager
Georg Brandl116aa622007-08-15 14:28:22 +000016
Christian Heimesd8654cf2007-12-02 15:22:16 +000017 This function is a :term:`decorator` that can be used to define a factory
18 function for :keyword:`with` statement context managers, without needing to
19 create a class or separate :meth:`__enter__` and :meth:`__exit__` methods.
Georg Brandl116aa622007-08-15 14:28:22 +000020
21 A simple example (this is not recommended as a real way of generating HTML!)::
22
Georg Brandl116aa622007-08-15 14:28:22 +000023 from contextlib import contextmanager
24
25 @contextmanager
26 def tag(name):
Georg Brandl6911e3c2007-09-04 07:15:32 +000027 print("<%s>" % name)
Georg Brandl116aa622007-08-15 14:28:22 +000028 yield
Georg Brandl6911e3c2007-09-04 07:15:32 +000029 print("</%s>" % name)
Georg Brandl116aa622007-08-15 14:28:22 +000030
31 >>> with tag("h1"):
Georg Brandl6911e3c2007-09-04 07:15:32 +000032 ... print("foo")
Georg Brandl116aa622007-08-15 14:28:22 +000033 ...
34 <h1>
35 foo
36 </h1>
37
Georg Brandl9afde1c2007-11-01 20:32:30 +000038 The function being decorated must return a :term:`generator`-iterator when
39 called. This iterator must yield exactly one value, which will be bound to
40 the targets in the :keyword:`with` statement's :keyword:`as` clause, if any.
Georg Brandl116aa622007-08-15 14:28:22 +000041
42 At the point where the generator yields, the block nested in the :keyword:`with`
43 statement is executed. The generator is then resumed after the block is exited.
44 If an unhandled exception occurs in the block, it is reraised inside the
45 generator at the point where the yield occurred. Thus, you can use a
46 :keyword:`try`...\ :keyword:`except`...\ :keyword:`finally` statement to trap
47 the error (if any), or ensure that some cleanup takes place. If an exception is
48 trapped merely in order to log it or to perform some action (rather than to
49 suppress it entirely), the generator must reraise that exception. Otherwise the
50 generator context manager will indicate to the :keyword:`with` statement that
51 the exception has been handled, and execution will resume with the statement
52 immediately following the :keyword:`with` statement.
53
Michael Foordb3a89842010-06-30 12:17:50 +000054 contextmanager uses :class:`ContextDecorator` so the context managers it
55 creates can be used as decorators as well as in :keyword:`with` statements.
56
57 .. versionchanged:: 3.2
58 Use of :class:`ContextDecorator`.
Georg Brandl116aa622007-08-15 14:28:22 +000059
Georg Brandl86e78d12010-07-18 13:43:32 +000060
Georg Brandl116aa622007-08-15 14:28:22 +000061.. function:: closing(thing)
62
63 Return a context manager that closes *thing* upon completion of the block. This
64 is basically equivalent to::
65
66 from contextlib import contextmanager
67
68 @contextmanager
69 def closing(thing):
70 try:
71 yield thing
72 finally:
73 thing.close()
74
75 And lets you write code like this::
76
Georg Brandl116aa622007-08-15 14:28:22 +000077 from contextlib import closing
Georg Brandl0f7ede42008-06-23 11:23:31 +000078 from urllib.request import urlopen
Georg Brandl116aa622007-08-15 14:28:22 +000079
Georg Brandl0f7ede42008-06-23 11:23:31 +000080 with closing(urlopen('http://www.python.org')) as page:
Georg Brandl116aa622007-08-15 14:28:22 +000081 for line in page:
Georg Brandl6911e3c2007-09-04 07:15:32 +000082 print(line)
Georg Brandl116aa622007-08-15 14:28:22 +000083
84 without needing to explicitly close ``page``. Even if an error occurs,
85 ``page.close()`` will be called when the :keyword:`with` block is exited.
86
87
Michael Foordb3a89842010-06-30 12:17:50 +000088.. class:: ContextDecorator()
89
90 A base class that enables a context manager to also be used as a decorator.
91
92 Context managers inheriting from ``ContextDecorator`` have to implement
93 ``__enter__`` and ``__exit__`` as normal. ``__exit__`` retains its optional
94 exception handling even when used as a decorator.
95
Georg Brandl86e78d12010-07-18 13:43:32 +000096 ``ContextDecorator`` is used by :func:`contextmanager`, so you get this
97 functionality automatically.
98
99 Example of ``ContextDecorator``::
Michael Foordb3a89842010-06-30 12:17:50 +0000100
101 from contextlib import ContextDecorator
102
103 class mycontext(ContextDecorator):
Georg Brandl86e78d12010-07-18 13:43:32 +0000104 def __enter__(self):
105 print('Starting')
106 return self
Michael Foordb3a89842010-06-30 12:17:50 +0000107
Georg Brandl86e78d12010-07-18 13:43:32 +0000108 def __exit__(self, *exc):
109 print('Finishing')
110 return False
Michael Foordb3a89842010-06-30 12:17:50 +0000111
112 >>> @mycontext()
113 ... def function():
Georg Brandl86e78d12010-07-18 13:43:32 +0000114 ... print('The bit in the middle')
Michael Foordb3a89842010-06-30 12:17:50 +0000115 ...
116 >>> function()
117 Starting
118 The bit in the middle
119 Finishing
120
121 >>> with mycontext():
Georg Brandl86e78d12010-07-18 13:43:32 +0000122 ... print('The bit in the middle')
Michael Foordb3a89842010-06-30 12:17:50 +0000123 ...
124 Starting
125 The bit in the middle
126 Finishing
127
Georg Brandl86e78d12010-07-18 13:43:32 +0000128 This change is just syntactic sugar for any construct of the following form::
129
130 def f():
131 with cm():
132 # Do stuff
133
134 ``ContextDecorator`` lets you instead write::
135
136 @cm()
137 def f():
138 # Do stuff
139
140 It makes it clear that the ``cm`` applies to the whole function, rather than
141 just a piece of it (and saving an indentation level is nice, too).
142
Michael Foordb3a89842010-06-30 12:17:50 +0000143 Existing context managers that already have a base class can be extended by
144 using ``ContextDecorator`` as a mixin class::
145
146 from contextlib import ContextDecorator
147
148 class mycontext(ContextBaseClass, ContextDecorator):
Georg Brandl86e78d12010-07-18 13:43:32 +0000149 def __enter__(self):
150 return self
Michael Foordb3a89842010-06-30 12:17:50 +0000151
Georg Brandl86e78d12010-07-18 13:43:32 +0000152 def __exit__(self, *exc):
153 return False
Michael Foordb3a89842010-06-30 12:17:50 +0000154
155 .. versionadded:: 3.2
156
157
Georg Brandl116aa622007-08-15 14:28:22 +0000158.. seealso::
159
160 :pep:`0343` - The "with" statement
161 The specification, background, and examples for the Python :keyword:`with`
162 statement.
163