blob: fba48f47d5514c95080034ccaa859778069788c5 [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]
Barry Warsawd8f870d2013-05-10 11:35:38 -0400262 # Hold onto the close method, but don't call it yet.
263 close_files = stack.pop_all().close
Nick Coghlan3267a302012-05-21 22:54:43 +1000264 # If opening any file fails, all previously opened files will be
265 # closed automatically. If all files are opened successfully,
266 # they will remain open even after the with statement ends.
Barry Warsawd8f870d2013-05-10 11:35:38 -0400267 # close_files() can then be invoked explicitly to close them all.
Nick Coghlan3267a302012-05-21 22:54:43 +1000268
269 .. method:: close()
270
271 Immediately unwinds the callback stack, invoking callbacks in the
272 reverse order of registration. For any context managers and exit
273 callbacks registered, the arguments passed in will indicate that no
274 exception occurred.
275
Nick Coghlan3267a302012-05-21 22:54:43 +1000276
277Examples and Recipes
278--------------------
279
280This section describes some examples and recipes for making effective use of
281the tools provided by :mod:`contextlib`.
282
283
Nick Coghlan27228272012-05-31 22:17:08 +1000284Supporting a variable number of context managers
285^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
286
287The primary use case for :class:`ExitStack` is the one given in the class
288documentation: supporting a variable number of context managers and other
289cleanup operations in a single :keyword:`with` statement. The variability
290may come from the number of context managers needed being driven by user
291input (such as opening a user specified collection of files), or from
292some of the context managers being optional::
293
294 with ExitStack() as stack:
295 for resource in resources:
296 stack.enter_context(resource)
297 if need_special resource:
298 special = acquire_special_resource()
299 stack.callback(release_special_resource, special)
300 # Perform operations that use the acquired resources
301
302As shown, :class:`ExitStack` also makes it quite easy to use :keyword:`with`
303statements to manage arbitrary resources that don't natively support the
304context management protocol.
305
306
307Simplifying support for single optional context managers
308^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
309
310In the specific case of a single optional context manager, :class:`ExitStack`
311instances can be used as a "do nothing" context manager, allowing a context
Nick Coghlanb7a455f2012-05-31 22:34:59 +1000312manager to easily be omitted without affecting the overall structure of
Nick Coghlan27228272012-05-31 22:17:08 +1000313the source code::
314
315 def debug_trace(details):
316 if __debug__:
317 return TraceContext(details)
318 # Don't do anything special with the context in release mode
319 return ExitStack()
320
321 with debug_trace():
322 # Suite is traced in debug mode, but runs normally otherwise
323
324
325Catching exceptions from ``__enter__`` methods
326^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
327
328It is occasionally desirable to catch exceptions from an ``__enter__``
329method implementation, *without* inadvertently catching exceptions from
330the :keyword:`with` statement body or the context manager's ``__exit__``
331method. By using :class:`ExitStack` the steps in the context management
332protocol can be separated slightly in order to allow this::
333
334 stack = ExitStack()
335 try:
336 x = stack.enter_context(cm)
337 except Exception:
338 # handle __enter__ exception
339 else:
340 with stack:
341 # Handle normal case
342
343Actually needing to do this is likely to indicate that the underlying API
344should be providing a direct resource management interface for use with
345:keyword:`try`/:keyword:`except`/:keyword:`finally` statements, but not
346all APIs are well designed in that regard. When a context manager is the
347only resource management API provided, then :class:`ExitStack` can make it
348easier to handle various situations that can't be handled directly in a
349:keyword:`with` statement.
350
351
Nick Coghlan3267a302012-05-21 22:54:43 +1000352Cleaning up in an ``__enter__`` implementation
353^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
354
355As noted in the documentation of :meth:`ExitStack.push`, this
356method can be useful in cleaning up an already allocated resource if later
357steps in the :meth:`__enter__` implementation fail.
358
359Here's an example of doing this for a context manager that accepts resource
360acquisition and release functions, along with an optional validation function,
361and maps them to the context management protocol::
362
363 from contextlib import contextmanager, ExitStack
364
Ezio Melottic9cfcf12013-03-11 09:42:40 +0200365 class ResourceManager:
Nick Coghlan3267a302012-05-21 22:54:43 +1000366
367 def __init__(self, acquire_resource, release_resource, check_resource_ok=None):
368 self.acquire_resource = acquire_resource
369 self.release_resource = release_resource
370 if check_resource_ok is None:
371 def check_resource_ok(resource):
372 return True
373 self.check_resource_ok = check_resource_ok
374
375 @contextmanager
376 def _cleanup_on_error(self):
377 with ExitStack() as stack:
378 stack.push(self)
379 yield
380 # The validation check passed and didn't raise an exception
381 # Accordingly, we want to keep the resource, and pass it
382 # back to our caller
383 stack.pop_all()
384
385 def __enter__(self):
386 resource = self.acquire_resource()
387 with self._cleanup_on_error():
388 if not self.check_resource_ok(resource):
389 msg = "Failed validation for {!r}"
390 raise RuntimeError(msg.format(resource))
391 return resource
392
393 def __exit__(self, *exc_details):
394 # We don't need to duplicate any of our resource release logic
395 self.release_resource()
396
397
398Replacing any use of ``try-finally`` and flag variables
399^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
400
401A pattern you will sometimes see is a ``try-finally`` statement with a flag
402variable to indicate whether or not the body of the ``finally`` clause should
403be executed. In its simplest form (that can't already be handled just by
404using an ``except`` clause instead), it looks something like this::
405
406 cleanup_needed = True
407 try:
408 result = perform_operation()
409 if result:
410 cleanup_needed = False
411 finally:
412 if cleanup_needed:
413 cleanup_resources()
414
415As with any ``try`` statement based code, this can cause problems for
416development and review, because the setup code and the cleanup code can end
417up being separated by arbitrarily long sections of code.
418
419:class:`ExitStack` makes it possible to instead register a callback for
420execution at the end of a ``with`` statement, and then later decide to skip
421executing that callback::
422
423 from contextlib import ExitStack
424
425 with ExitStack() as stack:
426 stack.callback(cleanup_resources)
427 result = perform_operation()
428 if result:
429 stack.pop_all()
430
431This allows the intended cleanup up behaviour to be made explicit up front,
432rather than requiring a separate flag variable.
433
434If a particular application uses this pattern a lot, it can be simplified
435even further by means of a small helper class::
436
437 from contextlib import ExitStack
438
439 class Callback(ExitStack):
440 def __init__(self, callback, *args, **kwds):
441 super(Callback, self).__init__()
442 self.callback(callback, *args, **kwds)
443
444 def cancel(self):
445 self.pop_all()
446
447 with Callback(cleanup_resources) as cb:
448 result = perform_operation()
449 if result:
450 cb.cancel()
451
452If the resource cleanup isn't already neatly bundled into a standalone
453function, then it is still possible to use the decorator form of
454:meth:`ExitStack.callback` to declare the resource cleanup in
455advance::
456
457 from contextlib import ExitStack
458
459 with ExitStack() as stack:
460 @stack.callback
461 def cleanup_resources():
462 ...
463 result = perform_operation()
464 if result:
465 stack.pop_all()
466
467Due to the way the decorator protocol works, a callback function
468declared this way cannot take any parameters. Instead, any resources to
469be released must be accessed as closure variables
470
471
472Using a context manager as a function decorator
473^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
474
475:class:`ContextDecorator` makes it possible to use a context manager in
476both an ordinary ``with`` statement and also as a function decorator.
477
478For example, it is sometimes useful to wrap functions or groups of statements
479with a logger that can track the time of entry and time of exit. Rather than
480writing both a function decorator and a context manager for the task,
481inheriting from :class:`ContextDecorator` provides both capabilities in a
482single definition::
483
484 from contextlib import ContextDecorator
485 import logging
486
487 logging.basicConfig(level=logging.INFO)
488
489 class track_entry_and_exit(ContextDecorator):
490 def __init__(self, name):
491 self.name = name
492
493 def __enter__(self):
494 logging.info('Entering: {}'.format(name))
495
496 def __exit__(self, exc_type, exc, exc_tb):
497 logging.info('Exiting: {}'.format(name))
498
499Instances of this class can be used as both a context manager::
500
501 with track_entry_and_exit('widget loader'):
502 print('Some time consuming activity goes here')
503 load_widget()
504
505And also as a function decorator::
506
507 @track_entry_and_exit('widget loader')
508 def activity():
509 print('Some time consuming activity goes here')
510 load_widget()
511
512Note that there is one additional limitation when using context managers
513as function decorators: there's no way to access the return value of
514:meth:`__enter__`. If that value is needed, then it is still necessary to use
515an explicit ``with`` statement.
516
Georg Brandl116aa622007-08-15 14:28:22 +0000517.. seealso::
518
519 :pep:`0343` - The "with" statement
520 The specification, background, and examples for the Python :keyword:`with`
521 statement.
522