blob: ca37f0f16a010cfa95fea24c2e01d171cbcd1c46 [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
15.. function:: contextmanager(func)
16
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
54
55.. function:: nested(mgr1[, mgr2[, ...]])
56
57 Combine multiple context managers into a single nested context manager.
58
Nick Coghlan4958cba2009-06-17 12:23:43 +000059 This function has been deprecated in favour of the multiple manager form
60 of the :keyword:`with` statement.
61
62 The one advantage of this function over the multiple manager form of the
63 :keyword:`with` statement is that argument unpacking allows it to be
64 used with a variable number of context managers as follows::
Georg Brandl116aa622007-08-15 14:28:22 +000065
66 from contextlib import nested
67
Nick Coghlan4958cba2009-06-17 12:23:43 +000068 with nested(*managers):
Georg Brandl116aa622007-08-15 14:28:22 +000069 do_something()
70
Georg Brandl116aa622007-08-15 14:28:22 +000071 Note that if the :meth:`__exit__` method of one of the nested context managers
72 indicates an exception should be suppressed, no exception information will be
73 passed to any remaining outer context managers. Similarly, if the
74 :meth:`__exit__` method of one of the nested managers raises an exception, any
75 previous exception state will be lost; the new exception will be passed to the
76 :meth:`__exit__` methods of any remaining outer context managers. In general,
77 :meth:`__exit__` methods should avoid raising exceptions, and in particular they
78 should not re-raise a passed-in exception.
79
Nick Coghlan4958cba2009-06-17 12:23:43 +000080 This function has two major quirks that have led to it being deprecated. Firstly,
81 as the context managers are all constructed before the function is invoked, the
82 :meth:`__new__` and :meth:`__init__` methods of the inner context managers are
83 not actually covered by the scope of the outer context managers. That means, for
84 example, that using :func:`nested` to open two files is a programming error as the
85 first file will not be closed promptly if an exception is thrown when opening
86 the second file.
87
88 Secondly, if the :meth:`__enter__` method of one of the inner context managers
89 raises an exception that is caught and suppressed by the :meth:`__exit__` method
90 of one of the outer context managers, this construct will raise
91 :exc:`RuntimeError` rather than skipping the body of the :keyword:`with`
92 statement.
93
94 Developers that need to support nesting of a variable number of context managers
95 can either use the :mod:`warnings` module to suppress the DeprecationWarning
96 raised by this function or else use this function as a model for an application
97 specific implementation.
98
Raymond Hettinger91e3b9d2009-05-28 22:20:03 +000099 .. deprecated:: 3.1
Nick Coghlan4958cba2009-06-17 12:23:43 +0000100 The with-statement now supports this functionality directly (without the
101 confusing error prone quirks).
102
Georg Brandl116aa622007-08-15 14:28:22 +0000103
104.. function:: closing(thing)
105
106 Return a context manager that closes *thing* upon completion of the block. This
107 is basically equivalent to::
108
109 from contextlib import contextmanager
110
111 @contextmanager
112 def closing(thing):
113 try:
114 yield thing
115 finally:
116 thing.close()
117
118 And lets you write code like this::
119
Georg Brandl116aa622007-08-15 14:28:22 +0000120 from contextlib import closing
Georg Brandl0f7ede42008-06-23 11:23:31 +0000121 from urllib.request import urlopen
Georg Brandl116aa622007-08-15 14:28:22 +0000122
Georg Brandl0f7ede42008-06-23 11:23:31 +0000123 with closing(urlopen('http://www.python.org')) as page:
Georg Brandl116aa622007-08-15 14:28:22 +0000124 for line in page:
Georg Brandl6911e3c2007-09-04 07:15:32 +0000125 print(line)
Georg Brandl116aa622007-08-15 14:28:22 +0000126
127 without needing to explicitly close ``page``. Even if an error occurs,
128 ``page.close()`` will be called when the :keyword:`with` block is exited.
129
130
131.. seealso::
132
133 :pep:`0343` - The "with" statement
134 The specification, background, and examples for the Python :keyword:`with`
135 statement.
136