blob: 154e3954a624bb3a1655cbe3424e54564aae6607 [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
Raymond Hettinger4f707fd2011-01-10 19:54:11 +00009--------------
10
Georg Brandl116aa622007-08-15 14:28:22 +000011This module provides utilities for common tasks involving the :keyword:`with`
12statement. For more information see also :ref:`typecontextmanager` and
13:ref:`context-managers`.
14
Georg Brandl116aa622007-08-15 14:28:22 +000015
Nick Coghlan3267a302012-05-21 22:54:43 +100016Utilities
17---------
18
19Functions and classes provided:
Georg Brandl116aa622007-08-15 14:28:22 +000020
Georg Brandl8a1caa22010-07-29 16:01:11 +000021.. decorator:: contextmanager
Georg Brandl116aa622007-08-15 14:28:22 +000022
Christian Heimesd8654cf2007-12-02 15:22:16 +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 Brandl116aa622007-08-15 14:28:22 +000026
27 A simple example (this is not recommended as a real way of generating HTML!)::
28
Georg Brandl116aa622007-08-15 14:28:22 +000029 from contextlib import contextmanager
30
31 @contextmanager
32 def tag(name):
Georg Brandl6911e3c2007-09-04 07:15:32 +000033 print("<%s>" % name)
Georg Brandl116aa622007-08-15 14:28:22 +000034 yield
Georg Brandl6911e3c2007-09-04 07:15:32 +000035 print("</%s>" % name)
Georg Brandl116aa622007-08-15 14:28:22 +000036
37 >>> with tag("h1"):
Georg Brandl6911e3c2007-09-04 07:15:32 +000038 ... print("foo")
Georg Brandl116aa622007-08-15 14:28:22 +000039 ...
40 <h1>
41 foo
42 </h1>
43
Georg Brandl9afde1c2007-11-01 20:32:30 +000044 The function being decorated must return a :term:`generator`-iterator when
45 called. This iterator must yield exactly one value, which will be bound to
46 the targets in the :keyword:`with` statement's :keyword:`as` clause, if any.
Georg Brandl116aa622007-08-15 14:28:22 +000047
48 At the point where the generator yields, the block nested in the :keyword:`with`
49 statement is executed. The generator is then resumed after the block is exited.
50 If an unhandled exception occurs in the block, it is reraised inside the
51 generator at the point where the yield occurred. Thus, you can use a
52 :keyword:`try`...\ :keyword:`except`...\ :keyword:`finally` statement to trap
53 the error (if any), or ensure that some cleanup takes place. If an exception is
54 trapped merely in order to log it or to perform some action (rather than to
55 suppress it entirely), the generator must reraise that exception. Otherwise the
56 generator context manager will indicate to the :keyword:`with` statement that
57 the exception has been handled, and execution will resume with the statement
58 immediately following the :keyword:`with` statement.
59
Nick Coghlan0ded3e32011-05-05 23:49:25 +100060 :func:`contextmanager` uses :class:`ContextDecorator` so the context managers
61 it creates can be used as decorators as well as in :keyword:`with` statements.
62 When used as a decorator, a new generator instance is implicitly created on
63 each function call (this allows the otherwise "one-shot" context managers
64 created by :func:`contextmanager` to meet the requirement that context
65 managers support multiple invocations in order to be used as decorators).
Michael Foordb3a89842010-06-30 12:17:50 +000066
67 .. versionchanged:: 3.2
68 Use of :class:`ContextDecorator`.
Georg Brandl116aa622007-08-15 14:28:22 +000069
Georg Brandl86e78d12010-07-18 13:43:32 +000070
Georg Brandl116aa622007-08-15 14:28:22 +000071.. function:: closing(thing)
72
73 Return a context manager that closes *thing* upon completion of the block. This
74 is basically equivalent to::
75
76 from contextlib import contextmanager
77
78 @contextmanager
79 def closing(thing):
80 try:
81 yield thing
82 finally:
83 thing.close()
84
85 And lets you write code like this::
86
Georg Brandl116aa622007-08-15 14:28:22 +000087 from contextlib import closing
Georg Brandl0f7ede42008-06-23 11:23:31 +000088 from urllib.request import urlopen
Georg Brandl116aa622007-08-15 14:28:22 +000089
Georg Brandl0f7ede42008-06-23 11:23:31 +000090 with closing(urlopen('http://www.python.org')) as page:
Georg Brandl116aa622007-08-15 14:28:22 +000091 for line in page:
Georg Brandl6911e3c2007-09-04 07:15:32 +000092 print(line)
Georg Brandl116aa622007-08-15 14:28:22 +000093
94 without needing to explicitly close ``page``. Even if an error occurs,
95 ``page.close()`` will be called when the :keyword:`with` block is exited.
96
97
Michael Foordb3a89842010-06-30 12:17:50 +000098.. class:: ContextDecorator()
99
100 A base class that enables a context manager to also be used as a decorator.
101
102 Context managers inheriting from ``ContextDecorator`` have to implement
103 ``__enter__`` and ``__exit__`` as normal. ``__exit__`` retains its optional
104 exception handling even when used as a decorator.
105
Georg Brandl86e78d12010-07-18 13:43:32 +0000106 ``ContextDecorator`` is used by :func:`contextmanager`, so you get this
107 functionality automatically.
108
109 Example of ``ContextDecorator``::
Michael Foordb3a89842010-06-30 12:17:50 +0000110
111 from contextlib import ContextDecorator
112
113 class mycontext(ContextDecorator):
Georg Brandl86e78d12010-07-18 13:43:32 +0000114 def __enter__(self):
115 print('Starting')
116 return self
Michael Foordb3a89842010-06-30 12:17:50 +0000117
Georg Brandl86e78d12010-07-18 13:43:32 +0000118 def __exit__(self, *exc):
119 print('Finishing')
120 return False
Michael Foordb3a89842010-06-30 12:17:50 +0000121
122 >>> @mycontext()
123 ... def function():
Georg Brandl86e78d12010-07-18 13:43:32 +0000124 ... print('The bit in the middle')
Michael Foordb3a89842010-06-30 12:17:50 +0000125 ...
126 >>> function()
127 Starting
128 The bit in the middle
129 Finishing
130
131 >>> with mycontext():
Georg Brandl86e78d12010-07-18 13:43:32 +0000132 ... print('The bit in the middle')
Michael Foordb3a89842010-06-30 12:17:50 +0000133 ...
134 Starting
135 The bit in the middle
136 Finishing
137
Georg Brandl86e78d12010-07-18 13:43:32 +0000138 This change is just syntactic sugar for any construct of the following form::
139
140 def f():
141 with cm():
142 # Do stuff
143
144 ``ContextDecorator`` lets you instead write::
145
146 @cm()
147 def f():
148 # Do stuff
149
150 It makes it clear that the ``cm`` applies to the whole function, rather than
151 just a piece of it (and saving an indentation level is nice, too).
152
Michael Foordb3a89842010-06-30 12:17:50 +0000153 Existing context managers that already have a base class can be extended by
154 using ``ContextDecorator`` as a mixin class::
155
156 from contextlib import ContextDecorator
157
158 class mycontext(ContextBaseClass, ContextDecorator):
Georg Brandl86e78d12010-07-18 13:43:32 +0000159 def __enter__(self):
160 return self
Michael Foordb3a89842010-06-30 12:17:50 +0000161
Georg Brandl86e78d12010-07-18 13:43:32 +0000162 def __exit__(self, *exc):
163 return False
Michael Foordb3a89842010-06-30 12:17:50 +0000164
Nick Coghlan0ded3e32011-05-05 23:49:25 +1000165 .. note::
166 As the decorated function must be able to be called multiple times, the
167 underlying context manager must support use in multiple :keyword:`with`
168 statements. If this is not the case, then the original construct with the
169 explicit :keyword:`with` statement inside the function should be used.
170
Michael Foordb3a89842010-06-30 12:17:50 +0000171 .. versionadded:: 3.2
172
173
Nick Coghlan3267a302012-05-21 22:54:43 +1000174.. class:: ExitStack()
175
176 A context manager that is designed to make it easy to programmatically
177 combine other context managers and cleanup functions, especially those
178 that are optional or otherwise driven by input data.
179
180 For example, a set of files may easily be handled in a single with
181 statement as follows::
182
183 with ExitStack() as stack:
184 files = [stack.enter_context(open(fname)) for fname in filenames]
185 # All opened files will automatically be closed at the end of
186 # the with statement, even if attempts to open files later
Andrew Svetlov5b898402012-12-18 21:26:36 +0200187 # in the list raise an exception
Nick Coghlan3267a302012-05-21 22:54:43 +1000188
189 Each instance maintains a stack of registered callbacks that are called in
190 reverse order when the instance is closed (either explicitly or implicitly
Nick Coghlan27228272012-05-31 22:17:08 +1000191 at the end of a :keyword:`with` statement). Note that callbacks are *not*
192 invoked implicitly when the context stack instance is garbage collected.
Nick Coghlan3267a302012-05-21 22:54:43 +1000193
194 This stack model is used so that context managers that acquire their
195 resources in their ``__init__`` method (such as file objects) can be
196 handled correctly.
197
198 Since registered callbacks are invoked in the reverse order of
Nick Coghlan27228272012-05-31 22:17:08 +1000199 registration, this ends up behaving as if multiple nested :keyword:`with`
Nick Coghlan3267a302012-05-21 22:54:43 +1000200 statements had been used with the registered set of callbacks. This even
201 extends to exception handling - if an inner callback suppresses or replaces
202 an exception, then outer callbacks will be passed arguments based on that
203 updated state.
204
205 This is a relatively low level API that takes care of the details of
206 correctly unwinding the stack of exit callbacks. It provides a suitable
207 foundation for higher level context managers that manipulate the exit
208 stack in application specific ways.
209
Nick Coghlana497b442012-05-22 23:02:00 +1000210 .. versionadded:: 3.3
211
Nick Coghlan3267a302012-05-21 22:54:43 +1000212 .. method:: enter_context(cm)
213
214 Enters a new context manager and adds its :meth:`__exit__` method to
215 the callback stack. The return value is the result of the context
216 manager's own :meth:`__enter__` method.
217
218 These context managers may suppress exceptions just as they normally
Nick Coghlan27228272012-05-31 22:17:08 +1000219 would if used directly as part of a :keyword:`with` statement.
Nick Coghlan3267a302012-05-21 22:54:43 +1000220
221 .. method:: push(exit)
222
223 Adds a context manager's :meth:`__exit__` method to the callback stack.
224
225 As ``__enter__`` is *not* invoked, this method can be used to cover
226 part of an :meth:`__enter__` implementation with a context manager's own
227 :meth:`__exit__` method.
228
229 If passed an object that is not a context manager, this method assumes
230 it is a callback with the same signature as a context manager's
231 :meth:`__exit__` method and adds it directly to the callback stack.
232
233 By returning true values, these callbacks can suppress exceptions the
234 same way context manager :meth:`__exit__` methods can.
235
236 The passed in object is returned from the function, allowing this
Nick Coghlan27228272012-05-31 22:17:08 +1000237 method to be used as a function decorator.
Nick Coghlan3267a302012-05-21 22:54:43 +1000238
239 .. method:: callback(callback, *args, **kwds)
240
241 Accepts an arbitrary callback function and arguments and adds it to
242 the callback stack.
243
244 Unlike the other methods, callbacks added this way cannot suppress
245 exceptions (as they are never passed the exception details).
246
247 The passed in callback is returned from the function, allowing this
Nick Coghlan27228272012-05-31 22:17:08 +1000248 method to be used as a function decorator.
Nick Coghlan3267a302012-05-21 22:54:43 +1000249
250 .. method:: pop_all()
251
252 Transfers the callback stack to a fresh :class:`ExitStack` instance
253 and returns it. No callbacks are invoked by this operation - instead,
254 they will now be invoked when the new stack is closed (either
Nick Coghlan27228272012-05-31 22:17:08 +1000255 explicitly or implicitly at the end of a :keyword:`with` statement).
Nick Coghlan3267a302012-05-21 22:54:43 +1000256
257 For example, a group of files can be opened as an "all or nothing"
258 operation as follows::
259
260 with ExitStack() as stack:
261 files = [stack.enter_context(open(fname)) for fname in filenames]
262 close_files = stack.pop_all().close
263 # If opening any file fails, all previously opened files will be
264 # closed automatically. If all files are opened successfully,
265 # they will remain open even after the with statement ends.
266 # close_files() can then be invoked explicitly to close them all
267
268 .. method:: close()
269
270 Immediately unwinds the callback stack, invoking callbacks in the
271 reverse order of registration. For any context managers and exit
272 callbacks registered, the arguments passed in will indicate that no
273 exception occurred.
274
Nick Coghlan3267a302012-05-21 22:54:43 +1000275
276Examples and Recipes
277--------------------
278
279This section describes some examples and recipes for making effective use of
280the tools provided by :mod:`contextlib`.
281
282
Nick Coghlan27228272012-05-31 22:17:08 +1000283Supporting a variable number of context managers
284^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
285
286The primary use case for :class:`ExitStack` is the one given in the class
287documentation: supporting a variable number of context managers and other
288cleanup operations in a single :keyword:`with` statement. The variability
289may come from the number of context managers needed being driven by user
290input (such as opening a user specified collection of files), or from
291some of the context managers being optional::
292
293 with ExitStack() as stack:
294 for resource in resources:
295 stack.enter_context(resource)
296 if need_special resource:
297 special = acquire_special_resource()
298 stack.callback(release_special_resource, special)
299 # Perform operations that use the acquired resources
300
301As shown, :class:`ExitStack` also makes it quite easy to use :keyword:`with`
302statements to manage arbitrary resources that don't natively support the
303context management protocol.
304
305
306Simplifying support for single optional context managers
307^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
308
309In the specific case of a single optional context manager, :class:`ExitStack`
310instances can be used as a "do nothing" context manager, allowing a context
Nick Coghlanb7a455f2012-05-31 22:34:59 +1000311manager to easily be omitted without affecting the overall structure of
Nick Coghlan27228272012-05-31 22:17:08 +1000312the source code::
313
314 def debug_trace(details):
315 if __debug__:
316 return TraceContext(details)
317 # Don't do anything special with the context in release mode
318 return ExitStack()
319
320 with debug_trace():
321 # Suite is traced in debug mode, but runs normally otherwise
322
323
324Catching exceptions from ``__enter__`` methods
325^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
326
327It is occasionally desirable to catch exceptions from an ``__enter__``
328method implementation, *without* inadvertently catching exceptions from
329the :keyword:`with` statement body or the context manager's ``__exit__``
330method. By using :class:`ExitStack` the steps in the context management
331protocol can be separated slightly in order to allow this::
332
333 stack = ExitStack()
334 try:
335 x = stack.enter_context(cm)
336 except Exception:
337 # handle __enter__ exception
338 else:
339 with stack:
340 # Handle normal case
341
342Actually needing to do this is likely to indicate that the underlying API
343should be providing a direct resource management interface for use with
344:keyword:`try`/:keyword:`except`/:keyword:`finally` statements, but not
345all APIs are well designed in that regard. When a context manager is the
346only resource management API provided, then :class:`ExitStack` can make it
347easier to handle various situations that can't be handled directly in a
348:keyword:`with` statement.
349
350
Nick Coghlan3267a302012-05-21 22:54:43 +1000351Cleaning up in an ``__enter__`` implementation
352^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
353
354As noted in the documentation of :meth:`ExitStack.push`, this
355method can be useful in cleaning up an already allocated resource if later
356steps in the :meth:`__enter__` implementation fail.
357
358Here's an example of doing this for a context manager that accepts resource
359acquisition and release functions, along with an optional validation function,
360and maps them to the context management protocol::
361
362 from contextlib import contextmanager, ExitStack
363
Ezio Melottic9cfcf12013-03-11 09:42:40 +0200364 class ResourceManager:
Nick Coghlan3267a302012-05-21 22:54:43 +1000365
366 def __init__(self, acquire_resource, release_resource, check_resource_ok=None):
367 self.acquire_resource = acquire_resource
368 self.release_resource = release_resource
369 if check_resource_ok is None:
370 def check_resource_ok(resource):
371 return True
372 self.check_resource_ok = check_resource_ok
373
374 @contextmanager
375 def _cleanup_on_error(self):
376 with ExitStack() as stack:
377 stack.push(self)
378 yield
379 # The validation check passed and didn't raise an exception
380 # Accordingly, we want to keep the resource, and pass it
381 # back to our caller
382 stack.pop_all()
383
384 def __enter__(self):
385 resource = self.acquire_resource()
386 with self._cleanup_on_error():
387 if not self.check_resource_ok(resource):
388 msg = "Failed validation for {!r}"
389 raise RuntimeError(msg.format(resource))
390 return resource
391
392 def __exit__(self, *exc_details):
393 # We don't need to duplicate any of our resource release logic
394 self.release_resource()
395
396
397Replacing any use of ``try-finally`` and flag variables
398^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
399
400A pattern you will sometimes see is a ``try-finally`` statement with a flag
401variable to indicate whether or not the body of the ``finally`` clause should
402be executed. In its simplest form (that can't already be handled just by
403using an ``except`` clause instead), it looks something like this::
404
405 cleanup_needed = True
406 try:
407 result = perform_operation()
408 if result:
409 cleanup_needed = False
410 finally:
411 if cleanup_needed:
412 cleanup_resources()
413
414As with any ``try`` statement based code, this can cause problems for
415development and review, because the setup code and the cleanup code can end
416up being separated by arbitrarily long sections of code.
417
418:class:`ExitStack` makes it possible to instead register a callback for
419execution at the end of a ``with`` statement, and then later decide to skip
420executing that callback::
421
422 from contextlib import ExitStack
423
424 with ExitStack() as stack:
425 stack.callback(cleanup_resources)
426 result = perform_operation()
427 if result:
428 stack.pop_all()
429
430This allows the intended cleanup up behaviour to be made explicit up front,
431rather than requiring a separate flag variable.
432
433If a particular application uses this pattern a lot, it can be simplified
434even further by means of a small helper class::
435
436 from contextlib import ExitStack
437
438 class Callback(ExitStack):
439 def __init__(self, callback, *args, **kwds):
440 super(Callback, self).__init__()
441 self.callback(callback, *args, **kwds)
442
443 def cancel(self):
444 self.pop_all()
445
446 with Callback(cleanup_resources) as cb:
447 result = perform_operation()
448 if result:
449 cb.cancel()
450
451If the resource cleanup isn't already neatly bundled into a standalone
452function, then it is still possible to use the decorator form of
453:meth:`ExitStack.callback` to declare the resource cleanup in
454advance::
455
456 from contextlib import ExitStack
457
458 with ExitStack() as stack:
459 @stack.callback
460 def cleanup_resources():
461 ...
462 result = perform_operation()
463 if result:
464 stack.pop_all()
465
466Due to the way the decorator protocol works, a callback function
467declared this way cannot take any parameters. Instead, any resources to
468be released must be accessed as closure variables
469
470
471Using a context manager as a function decorator
472^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
473
474:class:`ContextDecorator` makes it possible to use a context manager in
475both an ordinary ``with`` statement and also as a function decorator.
476
477For example, it is sometimes useful to wrap functions or groups of statements
478with a logger that can track the time of entry and time of exit. Rather than
479writing both a function decorator and a context manager for the task,
480inheriting from :class:`ContextDecorator` provides both capabilities in a
481single definition::
482
483 from contextlib import ContextDecorator
484 import logging
485
486 logging.basicConfig(level=logging.INFO)
487
488 class track_entry_and_exit(ContextDecorator):
489 def __init__(self, name):
490 self.name = name
491
492 def __enter__(self):
493 logging.info('Entering: {}'.format(name))
494
495 def __exit__(self, exc_type, exc, exc_tb):
496 logging.info('Exiting: {}'.format(name))
497
498Instances of this class can be used as both a context manager::
499
500 with track_entry_and_exit('widget loader'):
501 print('Some time consuming activity goes here')
502 load_widget()
503
504And also as a function decorator::
505
506 @track_entry_and_exit('widget loader')
507 def activity():
508 print('Some time consuming activity goes here')
509 load_widget()
510
511Note that there is one additional limitation when using context managers
512as function decorators: there's no way to access the return value of
513:meth:`__enter__`. If that value is needed, then it is still necessary to use
514an explicit ``with`` statement.
515
Georg Brandl116aa622007-08-15 14:28:22 +0000516.. seealso::
517
518 :pep:`0343` - The "with" statement
519 The specification, background, and examples for the Python :keyword:`with`
520 statement.
521