blob: 6f36864ac24fc12f452c3c91a7886b2df8902b12 [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
Georg Brandla7c17e52013-10-13 22:25:10 +020097
Nick Coghlan240f86d2013-10-17 23:40:57 +100098.. function:: suppress(*exceptions)
Raymond Hettingere318a882013-03-10 22:26:51 -070099
Nick Coghlan240f86d2013-10-17 23:40:57 +1000100 Return a context manager that suppresses any of the specified exceptions
101 if they occur in the body of a with statement and then resumes execution
102 with the first statement following the end of the with statement.
Raymond Hettingere318a882013-03-10 22:26:51 -0700103
Nick Coghlan240f86d2013-10-17 23:40:57 +1000104 As with any other mechanism that completely suppresses exceptions, this
105 context manager should be used only to cover very specific errors where
106 silently continuing with program execution is known to be the right
107 thing to do.
Nick Coghlanb4534ae2013-10-13 23:23:08 +1000108
Raymond Hettingere318a882013-03-10 22:26:51 -0700109 For example::
110
Nick Coghlan240f86d2013-10-17 23:40:57 +1000111 from contextlib import suppress
Raymond Hettingere318a882013-03-10 22:26:51 -0700112
Nick Coghlan240f86d2013-10-17 23:40:57 +1000113 with suppress(FileNotFoundError):
Raymond Hettingere318a882013-03-10 22:26:51 -0700114 os.remove('somefile.tmp')
115
Nick Coghlan240f86d2013-10-17 23:40:57 +1000116 with suppress(FileNotFoundError):
117 os.remove('someotherfile.tmp')
118
Raymond Hettingere318a882013-03-10 22:26:51 -0700119 This code is equivalent to::
120
121 try:
122 os.remove('somefile.tmp')
Nick Coghlanb4534ae2013-10-13 23:23:08 +1000123 except FileNotFoundError:
Raymond Hettingere318a882013-03-10 22:26:51 -0700124 pass
125
Nick Coghlan240f86d2013-10-17 23:40:57 +1000126 try:
127 os.remove('someotherfile.tmp')
128 except FileNotFoundError:
129 pass
130
Nick Coghlan8608d262013-10-20 00:30:51 +1000131 This context manager is :ref:`reentrant <reentrant-cms>`.
132
Raymond Hettingere318a882013-03-10 22:26:51 -0700133 .. versionadded:: 3.4
Georg Brandl116aa622007-08-15 14:28:22 +0000134
Nick Coghlanb4534ae2013-10-13 23:23:08 +1000135
Raymond Hettinger088cbf22013-10-10 00:46:57 -0700136.. function:: redirect_stdout(new_target)
137
138 Context manager for temporarily redirecting :data:`sys.stdout` to
139 another file or file-like object.
140
141 This tool adds flexibility to existing functions or classes whose output
142 is hardwired to stdout.
143
144 For example, the output of :func:`help` normally is sent to *sys.stdout*.
145 You can capture that output in a string by redirecting the output to a
146 :class:`io.StringIO` object::
147
148 f = io.StringIO()
149 with redirect_stdout(f):
150 help(pow)
151 s = f.getvalue()
152
153 To send the output of :func:`help` to a file on disk, redirect the output
154 to a regular file::
155
156 with open('help.txt', 'w') as f:
157 with redirect_stdout(f):
158 help(pow)
159
160 To send the output of :func:`help` to *sys.stderr*::
161
162 with redirect_stdout(sys.stderr):
163 help(pow)
164
Nick Coghlanb4534ae2013-10-13 23:23:08 +1000165 Note that the global side effect on :data:`sys.stdout` means that this
166 context manager is not suitable for use in library code and most threaded
167 applications. It also has no effect on the output of subprocesses.
168 However, it is still a useful approach for many utility scripts.
169
Nick Coghlan36d8ef92014-10-12 10:25:00 +1000170 This context manager is :ref:`reentrant <reentrant-cms>`.
Nick Coghlan8608d262013-10-20 00:30:51 +1000171
Raymond Hettinger088cbf22013-10-10 00:46:57 -0700172 .. versionadded:: 3.4
173
Georg Brandla7c17e52013-10-13 22:25:10 +0200174
Michael Foordb3a89842010-06-30 12:17:50 +0000175.. class:: ContextDecorator()
176
177 A base class that enables a context manager to also be used as a decorator.
178
179 Context managers inheriting from ``ContextDecorator`` have to implement
180 ``__enter__`` and ``__exit__`` as normal. ``__exit__`` retains its optional
181 exception handling even when used as a decorator.
182
Georg Brandl86e78d12010-07-18 13:43:32 +0000183 ``ContextDecorator`` is used by :func:`contextmanager`, so you get this
184 functionality automatically.
185
186 Example of ``ContextDecorator``::
Michael Foordb3a89842010-06-30 12:17:50 +0000187
188 from contextlib import ContextDecorator
189
190 class mycontext(ContextDecorator):
Georg Brandl86e78d12010-07-18 13:43:32 +0000191 def __enter__(self):
192 print('Starting')
193 return self
Michael Foordb3a89842010-06-30 12:17:50 +0000194
Georg Brandl86e78d12010-07-18 13:43:32 +0000195 def __exit__(self, *exc):
196 print('Finishing')
197 return False
Michael Foordb3a89842010-06-30 12:17:50 +0000198
199 >>> @mycontext()
200 ... def function():
Georg Brandl86e78d12010-07-18 13:43:32 +0000201 ... print('The bit in the middle')
Michael Foordb3a89842010-06-30 12:17:50 +0000202 ...
203 >>> function()
204 Starting
205 The bit in the middle
206 Finishing
207
208 >>> with mycontext():
Georg Brandl86e78d12010-07-18 13:43:32 +0000209 ... print('The bit in the middle')
Michael Foordb3a89842010-06-30 12:17:50 +0000210 ...
211 Starting
212 The bit in the middle
213 Finishing
214
Georg Brandl86e78d12010-07-18 13:43:32 +0000215 This change is just syntactic sugar for any construct of the following form::
216
217 def f():
218 with cm():
219 # Do stuff
220
221 ``ContextDecorator`` lets you instead write::
222
223 @cm()
224 def f():
225 # Do stuff
226
227 It makes it clear that the ``cm`` applies to the whole function, rather than
228 just a piece of it (and saving an indentation level is nice, too).
229
Michael Foordb3a89842010-06-30 12:17:50 +0000230 Existing context managers that already have a base class can be extended by
231 using ``ContextDecorator`` as a mixin class::
232
233 from contextlib import ContextDecorator
234
235 class mycontext(ContextBaseClass, ContextDecorator):
Georg Brandl86e78d12010-07-18 13:43:32 +0000236 def __enter__(self):
237 return self
Michael Foordb3a89842010-06-30 12:17:50 +0000238
Georg Brandl86e78d12010-07-18 13:43:32 +0000239 def __exit__(self, *exc):
240 return False
Michael Foordb3a89842010-06-30 12:17:50 +0000241
Nick Coghlan0ded3e32011-05-05 23:49:25 +1000242 .. note::
243 As the decorated function must be able to be called multiple times, the
244 underlying context manager must support use in multiple :keyword:`with`
245 statements. If this is not the case, then the original construct with the
246 explicit :keyword:`with` statement inside the function should be used.
247
Michael Foordb3a89842010-06-30 12:17:50 +0000248 .. versionadded:: 3.2
249
250
Nick Coghlan3267a302012-05-21 22:54:43 +1000251.. class:: ExitStack()
252
253 A context manager that is designed to make it easy to programmatically
254 combine other context managers and cleanup functions, especially those
255 that are optional or otherwise driven by input data.
256
257 For example, a set of files may easily be handled in a single with
258 statement as follows::
259
260 with ExitStack() as stack:
261 files = [stack.enter_context(open(fname)) for fname in filenames]
262 # All opened files will automatically be closed at the end of
263 # the with statement, even if attempts to open files later
Andrew Svetlov5b898402012-12-18 21:26:36 +0200264 # in the list raise an exception
Nick Coghlan3267a302012-05-21 22:54:43 +1000265
266 Each instance maintains a stack of registered callbacks that are called in
267 reverse order when the instance is closed (either explicitly or implicitly
Nick Coghlan27228272012-05-31 22:17:08 +1000268 at the end of a :keyword:`with` statement). Note that callbacks are *not*
269 invoked implicitly when the context stack instance is garbage collected.
Nick Coghlan3267a302012-05-21 22:54:43 +1000270
271 This stack model is used so that context managers that acquire their
272 resources in their ``__init__`` method (such as file objects) can be
273 handled correctly.
274
275 Since registered callbacks are invoked in the reverse order of
Nick Coghlan27228272012-05-31 22:17:08 +1000276 registration, this ends up behaving as if multiple nested :keyword:`with`
Nick Coghlan3267a302012-05-21 22:54:43 +1000277 statements had been used with the registered set of callbacks. This even
278 extends to exception handling - if an inner callback suppresses or replaces
279 an exception, then outer callbacks will be passed arguments based on that
280 updated state.
281
282 This is a relatively low level API that takes care of the details of
283 correctly unwinding the stack of exit callbacks. It provides a suitable
284 foundation for higher level context managers that manipulate the exit
285 stack in application specific ways.
286
Nick Coghlana497b442012-05-22 23:02:00 +1000287 .. versionadded:: 3.3
288
Nick Coghlan3267a302012-05-21 22:54:43 +1000289 .. method:: enter_context(cm)
290
291 Enters a new context manager and adds its :meth:`__exit__` method to
292 the callback stack. The return value is the result of the context
293 manager's own :meth:`__enter__` method.
294
295 These context managers may suppress exceptions just as they normally
Nick Coghlan27228272012-05-31 22:17:08 +1000296 would if used directly as part of a :keyword:`with` statement.
Nick Coghlan3267a302012-05-21 22:54:43 +1000297
298 .. method:: push(exit)
299
300 Adds a context manager's :meth:`__exit__` method to the callback stack.
301
302 As ``__enter__`` is *not* invoked, this method can be used to cover
303 part of an :meth:`__enter__` implementation with a context manager's own
304 :meth:`__exit__` method.
305
306 If passed an object that is not a context manager, this method assumes
307 it is a callback with the same signature as a context manager's
308 :meth:`__exit__` method and adds it directly to the callback stack.
309
310 By returning true values, these callbacks can suppress exceptions the
311 same way context manager :meth:`__exit__` methods can.
312
313 The passed in object is returned from the function, allowing this
Nick Coghlan27228272012-05-31 22:17:08 +1000314 method to be used as a function decorator.
Nick Coghlan3267a302012-05-21 22:54:43 +1000315
316 .. method:: callback(callback, *args, **kwds)
317
318 Accepts an arbitrary callback function and arguments and adds it to
319 the callback stack.
320
321 Unlike the other methods, callbacks added this way cannot suppress
322 exceptions (as they are never passed the exception details).
323
324 The passed in callback is returned from the function, allowing this
Nick Coghlan27228272012-05-31 22:17:08 +1000325 method to be used as a function decorator.
Nick Coghlan3267a302012-05-21 22:54:43 +1000326
327 .. method:: pop_all()
328
329 Transfers the callback stack to a fresh :class:`ExitStack` instance
330 and returns it. No callbacks are invoked by this operation - instead,
331 they will now be invoked when the new stack is closed (either
Nick Coghlan27228272012-05-31 22:17:08 +1000332 explicitly or implicitly at the end of a :keyword:`with` statement).
Nick Coghlan3267a302012-05-21 22:54:43 +1000333
334 For example, a group of files can be opened as an "all or nothing"
335 operation as follows::
336
337 with ExitStack() as stack:
338 files = [stack.enter_context(open(fname)) for fname in filenames]
Barry Warsawd8f870d2013-05-10 11:35:38 -0400339 # Hold onto the close method, but don't call it yet.
340 close_files = stack.pop_all().close
Nick Coghlan3267a302012-05-21 22:54:43 +1000341 # If opening any file fails, all previously opened files will be
342 # closed automatically. If all files are opened successfully,
343 # they will remain open even after the with statement ends.
Barry Warsawd8f870d2013-05-10 11:35:38 -0400344 # close_files() can then be invoked explicitly to close them all.
Nick Coghlan3267a302012-05-21 22:54:43 +1000345
346 .. method:: close()
347
348 Immediately unwinds the callback stack, invoking callbacks in the
349 reverse order of registration. For any context managers and exit
350 callbacks registered, the arguments passed in will indicate that no
351 exception occurred.
352
Nick Coghlan3267a302012-05-21 22:54:43 +1000353
354Examples and Recipes
355--------------------
356
357This section describes some examples and recipes for making effective use of
358the tools provided by :mod:`contextlib`.
359
360
Nick Coghlan27228272012-05-31 22:17:08 +1000361Supporting a variable number of context managers
362^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
363
364The primary use case for :class:`ExitStack` is the one given in the class
365documentation: supporting a variable number of context managers and other
366cleanup operations in a single :keyword:`with` statement. The variability
367may come from the number of context managers needed being driven by user
368input (such as opening a user specified collection of files), or from
369some of the context managers being optional::
370
371 with ExitStack() as stack:
372 for resource in resources:
373 stack.enter_context(resource)
Raymond Hettingere8e2df32014-05-25 18:06:04 -0700374 if need_special_resource():
Nick Coghlan27228272012-05-31 22:17:08 +1000375 special = acquire_special_resource()
376 stack.callback(release_special_resource, special)
377 # Perform operations that use the acquired resources
378
379As shown, :class:`ExitStack` also makes it quite easy to use :keyword:`with`
380statements to manage arbitrary resources that don't natively support the
381context management protocol.
382
383
384Simplifying support for single optional context managers
385^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
386
387In the specific case of a single optional context manager, :class:`ExitStack`
388instances can be used as a "do nothing" context manager, allowing a context
Nick Coghlanb7a455f2012-05-31 22:34:59 +1000389manager to easily be omitted without affecting the overall structure of
Nick Coghlan27228272012-05-31 22:17:08 +1000390the source code::
391
392 def debug_trace(details):
393 if __debug__:
394 return TraceContext(details)
395 # Don't do anything special with the context in release mode
396 return ExitStack()
397
398 with debug_trace():
399 # Suite is traced in debug mode, but runs normally otherwise
400
401
402Catching exceptions from ``__enter__`` methods
403^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
404
405It is occasionally desirable to catch exceptions from an ``__enter__``
406method implementation, *without* inadvertently catching exceptions from
407the :keyword:`with` statement body or the context manager's ``__exit__``
408method. By using :class:`ExitStack` the steps in the context management
409protocol can be separated slightly in order to allow this::
410
411 stack = ExitStack()
412 try:
413 x = stack.enter_context(cm)
414 except Exception:
415 # handle __enter__ exception
416 else:
417 with stack:
418 # Handle normal case
419
420Actually needing to do this is likely to indicate that the underlying API
421should be providing a direct resource management interface for use with
422:keyword:`try`/:keyword:`except`/:keyword:`finally` statements, but not
423all APIs are well designed in that regard. When a context manager is the
424only resource management API provided, then :class:`ExitStack` can make it
425easier to handle various situations that can't be handled directly in a
426:keyword:`with` statement.
427
428
Nick Coghlan3267a302012-05-21 22:54:43 +1000429Cleaning up in an ``__enter__`` implementation
430^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
431
432As noted in the documentation of :meth:`ExitStack.push`, this
433method can be useful in cleaning up an already allocated resource if later
434steps in the :meth:`__enter__` implementation fail.
435
436Here's an example of doing this for a context manager that accepts resource
437acquisition and release functions, along with an optional validation function,
438and maps them to the context management protocol::
439
440 from contextlib import contextmanager, ExitStack
441
Ezio Melottic9cfcf12013-03-11 09:42:40 +0200442 class ResourceManager:
Nick Coghlan3267a302012-05-21 22:54:43 +1000443
444 def __init__(self, acquire_resource, release_resource, check_resource_ok=None):
445 self.acquire_resource = acquire_resource
446 self.release_resource = release_resource
447 if check_resource_ok is None:
448 def check_resource_ok(resource):
449 return True
450 self.check_resource_ok = check_resource_ok
451
452 @contextmanager
453 def _cleanup_on_error(self):
454 with ExitStack() as stack:
455 stack.push(self)
456 yield
457 # The validation check passed and didn't raise an exception
458 # Accordingly, we want to keep the resource, and pass it
459 # back to our caller
460 stack.pop_all()
461
462 def __enter__(self):
463 resource = self.acquire_resource()
464 with self._cleanup_on_error():
465 if not self.check_resource_ok(resource):
466 msg = "Failed validation for {!r}"
467 raise RuntimeError(msg.format(resource))
468 return resource
469
470 def __exit__(self, *exc_details):
471 # We don't need to duplicate any of our resource release logic
472 self.release_resource()
473
474
475Replacing any use of ``try-finally`` and flag variables
476^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
477
478A pattern you will sometimes see is a ``try-finally`` statement with a flag
479variable to indicate whether or not the body of the ``finally`` clause should
480be executed. In its simplest form (that can't already be handled just by
481using an ``except`` clause instead), it looks something like this::
482
483 cleanup_needed = True
484 try:
485 result = perform_operation()
486 if result:
487 cleanup_needed = False
488 finally:
489 if cleanup_needed:
490 cleanup_resources()
491
492As with any ``try`` statement based code, this can cause problems for
493development and review, because the setup code and the cleanup code can end
494up being separated by arbitrarily long sections of code.
495
496:class:`ExitStack` makes it possible to instead register a callback for
497execution at the end of a ``with`` statement, and then later decide to skip
498executing that callback::
499
500 from contextlib import ExitStack
501
502 with ExitStack() as stack:
503 stack.callback(cleanup_resources)
504 result = perform_operation()
505 if result:
506 stack.pop_all()
507
508This allows the intended cleanup up behaviour to be made explicit up front,
509rather than requiring a separate flag variable.
510
511If a particular application uses this pattern a lot, it can be simplified
512even further by means of a small helper class::
513
514 from contextlib import ExitStack
515
516 class Callback(ExitStack):
517 def __init__(self, callback, *args, **kwds):
518 super(Callback, self).__init__()
519 self.callback(callback, *args, **kwds)
520
521 def cancel(self):
522 self.pop_all()
523
524 with Callback(cleanup_resources) as cb:
525 result = perform_operation()
526 if result:
527 cb.cancel()
528
529If the resource cleanup isn't already neatly bundled into a standalone
530function, then it is still possible to use the decorator form of
531:meth:`ExitStack.callback` to declare the resource cleanup in
532advance::
533
534 from contextlib import ExitStack
535
536 with ExitStack() as stack:
537 @stack.callback
538 def cleanup_resources():
539 ...
540 result = perform_operation()
541 if result:
542 stack.pop_all()
543
544Due to the way the decorator protocol works, a callback function
545declared this way cannot take any parameters. Instead, any resources to
546be released must be accessed as closure variables
547
548
549Using a context manager as a function decorator
550^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
551
552:class:`ContextDecorator` makes it possible to use a context manager in
553both an ordinary ``with`` statement and also as a function decorator.
554
555For example, it is sometimes useful to wrap functions or groups of statements
556with a logger that can track the time of entry and time of exit. Rather than
557writing both a function decorator and a context manager for the task,
558inheriting from :class:`ContextDecorator` provides both capabilities in a
559single definition::
560
561 from contextlib import ContextDecorator
562 import logging
563
564 logging.basicConfig(level=logging.INFO)
565
566 class track_entry_and_exit(ContextDecorator):
567 def __init__(self, name):
568 self.name = name
569
570 def __enter__(self):
Terry Jan Reedyf9bd9202014-10-10 16:00:18 -0400571 logging.info('Entering: {}'.format(self.name))
Nick Coghlan3267a302012-05-21 22:54:43 +1000572
573 def __exit__(self, exc_type, exc, exc_tb):
Terry Jan Reedyf9bd9202014-10-10 16:00:18 -0400574 logging.info('Exiting: {}'.format(self.name))
Nick Coghlan3267a302012-05-21 22:54:43 +1000575
576Instances of this class can be used as both a context manager::
577
578 with track_entry_and_exit('widget loader'):
579 print('Some time consuming activity goes here')
580 load_widget()
581
582And also as a function decorator::
583
584 @track_entry_and_exit('widget loader')
585 def activity():
586 print('Some time consuming activity goes here')
587 load_widget()
588
589Note that there is one additional limitation when using context managers
590as function decorators: there's no way to access the return value of
591:meth:`__enter__`. If that value is needed, then it is still necessary to use
592an explicit ``with`` statement.
593
Georg Brandl116aa622007-08-15 14:28:22 +0000594.. seealso::
595
596 :pep:`0343` - The "with" statement
597 The specification, background, and examples for the Python :keyword:`with`
598 statement.
599
Nick Coghlan0acceb72013-10-20 13:22:21 +1000600.. _single-use-reusable-and-reentrant-cms:
Nick Coghlan8608d262013-10-20 00:30:51 +1000601
Nick Coghlan0acceb72013-10-20 13:22:21 +1000602Single use, reusable and reentrant context managers
603---------------------------------------------------
Nick Coghlan8608d262013-10-20 00:30:51 +1000604
605Most context managers are written in a way that means they can only be
606used effectively in a :keyword:`with` statement once. These single use
607context managers must be created afresh each time they're used -
608attempting to use them a second time will trigger an exception or
609otherwise not work correctly.
610
611This common limitation means that it is generally advisable to create
612context managers directly in the header of the :keyword:`with` statement
613where they are used (as shown in all of the usage examples above).
614
615Files are an example of effectively single use context managers, since
616the first :keyword:`with` statement will close the file, preventing any
617further IO operations using that file object.
618
619Context managers created using :func:`contextmanager` are also single use
620context managers, and will complain about the underlying generator failing
621to yield if an attempt is made to use them a second time::
622
623 >>> from contextlib import contextmanager
624 >>> @contextmanager
625 ... def singleuse():
626 ... print("Before")
627 ... yield
628 ... print("After")
629 ...
630 >>> cm = singleuse()
631 >>> with cm:
632 ... pass
633 ...
634 Before
635 After
636 >>> with cm:
637 ... pass
638 ...
639 Traceback (most recent call last):
640 ...
641 RuntimeError: generator didn't yield
642
643
644.. _reentrant-cms:
645
646Reentrant context managers
647^^^^^^^^^^^^^^^^^^^^^^^^^^
648
649More sophisticated context managers may be "reentrant". These context
650managers can not only be used in multiple :keyword:`with` statements,
651but may also be used *inside* a :keyword:`with` statement that is already
652using the same context manager.
653
Nick Coghlan8e113b42013-11-03 17:00:51 +1000654:class:`threading.RLock` is an example of a reentrant context manager, as are
655:func:`suppress` and :func:`redirect_stdout`. Here's a very simple example of
656reentrant use::
Nick Coghlan8608d262013-10-20 00:30:51 +1000657
Nick Coghlan8e113b42013-11-03 17:00:51 +1000658 >>> from contextlib import redirect_stdout
659 >>> from io import StringIO
660 >>> stream = StringIO()
661 >>> write_to_stream = redirect_stdout(stream)
662 >>> with write_to_stream:
663 ... print("This is written to the stream rather than stdout")
664 ... with write_to_stream:
665 ... print("This is also written to the stream")
Nick Coghlan8608d262013-10-20 00:30:51 +1000666 ...
Nick Coghlan8e113b42013-11-03 17:00:51 +1000667 >>> print("This is written directly to stdout")
668 This is written directly to stdout
669 >>> print(stream.getvalue())
670 This is written to the stream rather than stdout
671 This is also written to the stream
672
673Real world examples of reentrancy are more likely to involve multiple
674functions calling each other and hence be far more complicated than this
675example.
676
677Note also that being reentrant is *not* the same thing as being thread safe.
678:func:`redirect_stdout`, for example, is definitely not thread safe, as it
679makes a global modification to the system state by binding :data:`sys.stdout`
680to a different stream.
Nick Coghlan8608d262013-10-20 00:30:51 +1000681
682
683.. _reusable-cms:
684
685Reusable context managers
686^^^^^^^^^^^^^^^^^^^^^^^^^
687
688Distinct from both single use and reentrant context managers are "reusable"
689context managers (or, to be completely explicit, "reusable, but not
690reentrant" context managers, since reentrant context managers are also
691reusable). These context managers support being used multiple times, but
692will fail (or otherwise not work correctly) if the specific context manager
693instance has already been used in a containing with statement.
694
Nick Coghlan8e113b42013-11-03 17:00:51 +1000695:class:`threading.Lock` is an example of a reusable, but not reentrant,
696context manager (for a reentrant lock, it is necessary to use
697:class:`threading.RLock` instead).
Nick Coghlan8608d262013-10-20 00:30:51 +1000698
Nick Coghlan8e113b42013-11-03 17:00:51 +1000699Another example of a reusable, but not reentrant, context manager is
700:class:`ExitStack`, as it invokes *all* currently registered callbacks
701when leaving any with statement, regardless of where those callbacks
702were added::
Nick Coghlan8608d262013-10-20 00:30:51 +1000703
Nick Coghlan8e113b42013-11-03 17:00:51 +1000704 >>> from contextlib import ExitStack
705 >>> stack = ExitStack()
706 >>> with stack:
707 ... stack.callback(print, "Callback: from first context")
708 ... print("Leaving first context")
Nick Coghlan8608d262013-10-20 00:30:51 +1000709 ...
Nick Coghlan8e113b42013-11-03 17:00:51 +1000710 Leaving first context
711 Callback: from first context
712 >>> with stack:
713 ... stack.callback(print, "Callback: from second context")
714 ... print("Leaving second context")
715 ...
716 Leaving second context
717 Callback: from second context
718 >>> with stack:
719 ... stack.callback(print, "Callback: from outer context")
720 ... with stack:
721 ... stack.callback(print, "Callback: from inner context")
722 ... print("Leaving inner context")
723 ... print("Leaving outer context")
724 ...
725 Leaving inner context
726 Callback: from inner context
727 Callback: from outer context
728 Leaving outer context
729
730As the output from the example shows, reusing a single stack object across
731multiple with statements works correctly, but attempting to nest them
732will cause the stack to be cleared at the end of the innermost with
733statement, which is unlikely to be desirable behaviour.
734
735Using separate :class:`ExitStack` instances instead of reusing a single
736instance avoids that problem::
737
738 >>> from contextlib import ExitStack
739 >>> with ExitStack() as outer_stack:
740 ... outer_stack.callback(print, "Callback: from outer context")
741 ... with ExitStack() as inner_stack:
742 ... inner_stack.callback(print, "Callback: from inner context")
743 ... print("Leaving inner context")
744 ... print("Leaving outer context")
745 ...
746 Leaving inner context
747 Callback: from inner context
748 Leaving outer context
749 Callback: from outer context