blob: 183da706031f7250f8ce1bbad767984591ef72f4 [file] [log] [blame]
Georg Brandl42a82642009-06-08 07:57:35 +00001:mod:`contextlib` --- Utilities for :keyword:`with`\ -statement contexts
2========================================================================
Georg Brandl8ec7f652007-08-15 14:28:01 +00003
4.. module:: contextlib
5 :synopsis: Utilities for with-statement contexts.
6
7
8.. versionadded:: 2.5
9
Éric Araujo29a0b572011-08-19 02:14:03 +020010**Source code:** :source:`Lib/contextlib.py`
11
12--------------
13
Georg Brandl8ec7f652007-08-15 14:28:01 +000014This module provides utilities for common tasks involving the :keyword:`with`
15statement. For more information see also :ref:`typecontextmanager` and
16:ref:`context-managers`.
17
18Functions provided:
19
20
21.. function:: contextmanager(func)
22
Georg Brandl584265b2007-12-02 14:58:50 +000023 This function is a :term:`decorator` that can be used to define a factory
24 function for :keyword:`with` statement context managers, without needing to
25 create a class or separate :meth:`__enter__` and :meth:`__exit__` methods.
Georg Brandl8ec7f652007-08-15 14:28:01 +000026
Tal Einatf7e60a62018-07-24 00:38:34 +030027 While many objects natively support use in with statements, sometimes a
28 resource needs to be managed that isn't a context manager in its own right,
29 and doesn't implement a ``close()`` method for use with ``contextlib.closing``
30
31 An abstract example would be the following to ensure correct resource
32 management::
Georg Brandl8ec7f652007-08-15 14:28:01 +000033
Georg Brandl8ec7f652007-08-15 14:28:01 +000034 from contextlib import contextmanager
35
36 @contextmanager
Tal Einatf7e60a62018-07-24 00:38:34 +030037 def managed_resource(*args, **kwds):
38 # Code to acquire resource, e.g.:
39 resource = acquire_resource(*args, **kwds)
40 try:
41 yield resource
42 finally:
43 # Code to release resource, e.g.:
44 release_resource(resource)
Georg Brandl8ec7f652007-08-15 14:28:01 +000045
Tal Einatf7e60a62018-07-24 00:38:34 +030046 >>> with managed_resource(timeout=3600) as resource:
47 ... # Resource is released at the end of this block,
48 ... # even if code in the block raises an exception
Georg Brandl8ec7f652007-08-15 14:28:01 +000049
Georg Brandlcf3fb252007-10-21 10:52:38 +000050 The function being decorated must return a :term:`generator`-iterator when
51 called. This iterator must yield exactly one value, which will be bound to
52 the targets in the :keyword:`with` statement's :keyword:`as` clause, if any.
Georg Brandl8ec7f652007-08-15 14:28:01 +000053
54 At the point where the generator yields, the block nested in the :keyword:`with`
55 statement is executed. The generator is then resumed after the block is exited.
56 If an unhandled exception occurs in the block, it is reraised inside the
57 generator at the point where the yield occurred. Thus, you can use a
58 :keyword:`try`...\ :keyword:`except`...\ :keyword:`finally` statement to trap
59 the error (if any), or ensure that some cleanup takes place. If an exception is
60 trapped merely in order to log it or to perform some action (rather than to
61 suppress it entirely), the generator must reraise that exception. Otherwise the
62 generator context manager will indicate to the :keyword:`with` statement that
63 the exception has been handled, and execution will resume with the statement
64 immediately following the :keyword:`with` statement.
65
66
67.. function:: nested(mgr1[, mgr2[, ...]])
68
69 Combine multiple context managers into a single nested context manager.
70
Nick Coghlan7c2bc832009-06-17 12:12:15 +000071 This function has been deprecated in favour of the multiple manager form
72 of the :keyword:`with` statement.
73
74 The one advantage of this function over the multiple manager form of the
75 :keyword:`with` statement is that argument unpacking allows it to be
76 used with a variable number of context managers as follows::
Georg Brandl8ec7f652007-08-15 14:28:01 +000077
78 from contextlib import nested
79
Nick Coghlan7c2bc832009-06-17 12:12:15 +000080 with nested(*managers):
Georg Brandl8ec7f652007-08-15 14:28:01 +000081 do_something()
82
Georg Brandl8ec7f652007-08-15 14:28:01 +000083 Note that if the :meth:`__exit__` method of one of the nested context managers
84 indicates an exception should be suppressed, no exception information will be
85 passed to any remaining outer context managers. Similarly, if the
86 :meth:`__exit__` method of one of the nested managers raises an exception, any
87 previous exception state will be lost; the new exception will be passed to the
88 :meth:`__exit__` methods of any remaining outer context managers. In general,
89 :meth:`__exit__` methods should avoid raising exceptions, and in particular they
90 should not re-raise a passed-in exception.
91
Nick Coghlan7c2bc832009-06-17 12:12:15 +000092 This function has two major quirks that have led to it being deprecated. Firstly,
93 as the context managers are all constructed before the function is invoked, the
94 :meth:`__new__` and :meth:`__init__` methods of the inner context managers are
95 not actually covered by the scope of the outer context managers. That means, for
96 example, that using :func:`nested` to open two files is a programming error as the
97 first file will not be closed promptly if an exception is thrown when opening
98 the second file.
99
100 Secondly, if the :meth:`__enter__` method of one of the inner context managers
101 raises an exception that is caught and suppressed by the :meth:`__exit__` method
102 of one of the outer context managers, this construct will raise
103 :exc:`RuntimeError` rather than skipping the body of the :keyword:`with`
104 statement.
105
106 Developers that need to support nesting of a variable number of context managers
107 can either use the :mod:`warnings` module to suppress the DeprecationWarning
108 raised by this function or else use this function as a model for an application
109 specific implementation.
110
Raymond Hettinger822b87f2009-05-29 01:46:48 +0000111 .. deprecated:: 2.7
Nick Coghlan7c2bc832009-06-17 12:12:15 +0000112 The with-statement now supports this functionality directly (without the
113 confusing error prone quirks).
Georg Brandl8ec7f652007-08-15 14:28:01 +0000114
115.. function:: closing(thing)
116
117 Return a context manager that closes *thing* upon completion of the block. This
118 is basically equivalent to::
119
120 from contextlib import contextmanager
121
122 @contextmanager
123 def closing(thing):
124 try:
125 yield thing
126 finally:
127 thing.close()
128
129 And lets you write code like this::
130
Georg Brandl8ec7f652007-08-15 14:28:01 +0000131 from contextlib import closing
132 import urllib
133
134 with closing(urllib.urlopen('http://www.python.org')) as page:
135 for line in page:
136 print line
137
138 without needing to explicitly close ``page``. Even if an error occurs,
139 ``page.close()`` will be called when the :keyword:`with` block is exited.
140
141
142.. seealso::
143
Serhiy Storchaka838b1332016-03-31 15:31:04 +0300144 :pep:`343` - The "with" statement
Georg Brandl8ec7f652007-08-15 14:28:01 +0000145 The specification, background, and examples for the Python :keyword:`with`
146 statement.
147