blob: 5c56a5d494f00d72d7feb4c019e0257b47d7733f [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
Raymond Hettinger10480942011-01-10 03:26:08 +00007**Source code:** :source:`Lib/contextlib.py`
Georg Brandl116aa622007-08-15 14:28:22 +00008
Georg Brandl116aa622007-08-15 14:28:22 +00009This module provides utilities for common tasks involving the :keyword:`with`
10statement. For more information see also :ref:`typecontextmanager` and
11:ref:`context-managers`.
12
13Functions provided:
14
15
Georg Brandl8a1caa22010-07-29 16:01:11 +000016.. decorator:: contextmanager
Georg Brandl116aa622007-08-15 14:28:22 +000017
Christian Heimesd8654cf2007-12-02 15:22:16 +000018 This function is a :term:`decorator` that can be used to define a factory
19 function for :keyword:`with` statement context managers, without needing to
20 create a class or separate :meth:`__enter__` and :meth:`__exit__` methods.
Georg Brandl116aa622007-08-15 14:28:22 +000021
22 A simple example (this is not recommended as a real way of generating HTML!)::
23
Georg Brandl116aa622007-08-15 14:28:22 +000024 from contextlib import contextmanager
25
26 @contextmanager
27 def tag(name):
Georg Brandl6911e3c2007-09-04 07:15:32 +000028 print("<%s>" % name)
Georg Brandl116aa622007-08-15 14:28:22 +000029 yield
Georg Brandl6911e3c2007-09-04 07:15:32 +000030 print("</%s>" % name)
Georg Brandl116aa622007-08-15 14:28:22 +000031
32 >>> with tag("h1"):
Georg Brandl6911e3c2007-09-04 07:15:32 +000033 ... print("foo")
Georg Brandl116aa622007-08-15 14:28:22 +000034 ...
35 <h1>
36 foo
37 </h1>
38
Georg Brandl9afde1c2007-11-01 20:32:30 +000039 The function being decorated must return a :term:`generator`-iterator when
40 called. This iterator must yield exactly one value, which will be bound to
41 the targets in the :keyword:`with` statement's :keyword:`as` clause, if any.
Georg Brandl116aa622007-08-15 14:28:22 +000042
43 At the point where the generator yields, the block nested in the :keyword:`with`
44 statement is executed. The generator is then resumed after the block is exited.
45 If an unhandled exception occurs in the block, it is reraised inside the
46 generator at the point where the yield occurred. Thus, you can use a
47 :keyword:`try`...\ :keyword:`except`...\ :keyword:`finally` statement to trap
48 the error (if any), or ensure that some cleanup takes place. If an exception is
49 trapped merely in order to log it or to perform some action (rather than to
50 suppress it entirely), the generator must reraise that exception. Otherwise the
51 generator context manager will indicate to the :keyword:`with` statement that
52 the exception has been handled, and execution will resume with the statement
53 immediately following the :keyword:`with` statement.
54
Michael Foordb3a89842010-06-30 12:17:50 +000055 contextmanager uses :class:`ContextDecorator` so the context managers it
56 creates can be used as decorators as well as in :keyword:`with` statements.
57
58 .. versionchanged:: 3.2
59 Use of :class:`ContextDecorator`.
Georg Brandl116aa622007-08-15 14:28:22 +000060
Georg Brandl86e78d12010-07-18 13:43:32 +000061
Georg Brandl116aa622007-08-15 14:28:22 +000062.. function:: closing(thing)
63
64 Return a context manager that closes *thing* upon completion of the block. This
65 is basically equivalent to::
66
67 from contextlib import contextmanager
68
69 @contextmanager
70 def closing(thing):
71 try:
72 yield thing
73 finally:
74 thing.close()
75
76 And lets you write code like this::
77
Georg Brandl116aa622007-08-15 14:28:22 +000078 from contextlib import closing
Georg Brandl0f7ede42008-06-23 11:23:31 +000079 from urllib.request import urlopen
Georg Brandl116aa622007-08-15 14:28:22 +000080
Georg Brandl0f7ede42008-06-23 11:23:31 +000081 with closing(urlopen('http://www.python.org')) as page:
Georg Brandl116aa622007-08-15 14:28:22 +000082 for line in page:
Georg Brandl6911e3c2007-09-04 07:15:32 +000083 print(line)
Georg Brandl116aa622007-08-15 14:28:22 +000084
85 without needing to explicitly close ``page``. Even if an error occurs,
86 ``page.close()`` will be called when the :keyword:`with` block is exited.
87
88
Michael Foordb3a89842010-06-30 12:17:50 +000089.. class:: ContextDecorator()
90
91 A base class that enables a context manager to also be used as a decorator.
92
93 Context managers inheriting from ``ContextDecorator`` have to implement
94 ``__enter__`` and ``__exit__`` as normal. ``__exit__`` retains its optional
95 exception handling even when used as a decorator.
96
Georg Brandl86e78d12010-07-18 13:43:32 +000097 ``ContextDecorator`` is used by :func:`contextmanager`, so you get this
98 functionality automatically.
99
100 Example of ``ContextDecorator``::
Michael Foordb3a89842010-06-30 12:17:50 +0000101
102 from contextlib import ContextDecorator
103
104 class mycontext(ContextDecorator):
Georg Brandl86e78d12010-07-18 13:43:32 +0000105 def __enter__(self):
106 print('Starting')
107 return self
Michael Foordb3a89842010-06-30 12:17:50 +0000108
Georg Brandl86e78d12010-07-18 13:43:32 +0000109 def __exit__(self, *exc):
110 print('Finishing')
111 return False
Michael Foordb3a89842010-06-30 12:17:50 +0000112
113 >>> @mycontext()
114 ... def function():
Georg Brandl86e78d12010-07-18 13:43:32 +0000115 ... print('The bit in the middle')
Michael Foordb3a89842010-06-30 12:17:50 +0000116 ...
117 >>> function()
118 Starting
119 The bit in the middle
120 Finishing
121
122 >>> with mycontext():
Georg Brandl86e78d12010-07-18 13:43:32 +0000123 ... print('The bit in the middle')
Michael Foordb3a89842010-06-30 12:17:50 +0000124 ...
125 Starting
126 The bit in the middle
127 Finishing
128
Georg Brandl86e78d12010-07-18 13:43:32 +0000129 This change is just syntactic sugar for any construct of the following form::
130
131 def f():
132 with cm():
133 # Do stuff
134
135 ``ContextDecorator`` lets you instead write::
136
137 @cm()
138 def f():
139 # Do stuff
140
141 It makes it clear that the ``cm`` applies to the whole function, rather than
142 just a piece of it (and saving an indentation level is nice, too).
143
Michael Foordb3a89842010-06-30 12:17:50 +0000144 Existing context managers that already have a base class can be extended by
145 using ``ContextDecorator`` as a mixin class::
146
147 from contextlib import ContextDecorator
148
149 class mycontext(ContextBaseClass, ContextDecorator):
Georg Brandl86e78d12010-07-18 13:43:32 +0000150 def __enter__(self):
151 return self
Michael Foordb3a89842010-06-30 12:17:50 +0000152
Georg Brandl86e78d12010-07-18 13:43:32 +0000153 def __exit__(self, *exc):
154 return False
Michael Foordb3a89842010-06-30 12:17:50 +0000155
156 .. versionadded:: 3.2
157
158
Georg Brandl116aa622007-08-15 14:28:22 +0000159.. seealso::
160
161 :pep:`0343` - The "with" statement
162 The specification, background, and examples for the Python :keyword:`with`
163 statement.
164