blob: 669c04aedea806675e437edee856fc7ea461d4b3 [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
Raymond Hettingere318a882013-03-10 22:26:51 -0700131 .. versionadded:: 3.4
Georg Brandl116aa622007-08-15 14:28:22 +0000132
Nick Coghlanb4534ae2013-10-13 23:23:08 +1000133
Raymond Hettinger088cbf22013-10-10 00:46:57 -0700134.. function:: redirect_stdout(new_target)
135
136 Context manager for temporarily redirecting :data:`sys.stdout` to
137 another file or file-like object.
138
139 This tool adds flexibility to existing functions or classes whose output
140 is hardwired to stdout.
141
142 For example, the output of :func:`help` normally is sent to *sys.stdout*.
143 You can capture that output in a string by redirecting the output to a
144 :class:`io.StringIO` object::
145
146 f = io.StringIO()
147 with redirect_stdout(f):
148 help(pow)
149 s = f.getvalue()
150
151 To send the output of :func:`help` to a file on disk, redirect the output
152 to a regular file::
153
154 with open('help.txt', 'w') as f:
155 with redirect_stdout(f):
156 help(pow)
157
158 To send the output of :func:`help` to *sys.stderr*::
159
160 with redirect_stdout(sys.stderr):
161 help(pow)
162
Nick Coghlanb4534ae2013-10-13 23:23:08 +1000163 Note that the global side effect on :data:`sys.stdout` means that this
164 context manager is not suitable for use in library code and most threaded
165 applications. It also has no effect on the output of subprocesses.
166 However, it is still a useful approach for many utility scripts.
167
Raymond Hettinger088cbf22013-10-10 00:46:57 -0700168 .. versionadded:: 3.4
169
Georg Brandla7c17e52013-10-13 22:25:10 +0200170
Michael Foordb3a89842010-06-30 12:17:50 +0000171.. class:: ContextDecorator()
172
173 A base class that enables a context manager to also be used as a decorator.
174
175 Context managers inheriting from ``ContextDecorator`` have to implement
176 ``__enter__`` and ``__exit__`` as normal. ``__exit__`` retains its optional
177 exception handling even when used as a decorator.
178
Georg Brandl86e78d12010-07-18 13:43:32 +0000179 ``ContextDecorator`` is used by :func:`contextmanager`, so you get this
180 functionality automatically.
181
182 Example of ``ContextDecorator``::
Michael Foordb3a89842010-06-30 12:17:50 +0000183
184 from contextlib import ContextDecorator
185
186 class mycontext(ContextDecorator):
Georg Brandl86e78d12010-07-18 13:43:32 +0000187 def __enter__(self):
188 print('Starting')
189 return self
Michael Foordb3a89842010-06-30 12:17:50 +0000190
Georg Brandl86e78d12010-07-18 13:43:32 +0000191 def __exit__(self, *exc):
192 print('Finishing')
193 return False
Michael Foordb3a89842010-06-30 12:17:50 +0000194
195 >>> @mycontext()
196 ... def function():
Georg Brandl86e78d12010-07-18 13:43:32 +0000197 ... print('The bit in the middle')
Michael Foordb3a89842010-06-30 12:17:50 +0000198 ...
199 >>> function()
200 Starting
201 The bit in the middle
202 Finishing
203
204 >>> with mycontext():
Georg Brandl86e78d12010-07-18 13:43:32 +0000205 ... print('The bit in the middle')
Michael Foordb3a89842010-06-30 12:17:50 +0000206 ...
207 Starting
208 The bit in the middle
209 Finishing
210
Georg Brandl86e78d12010-07-18 13:43:32 +0000211 This change is just syntactic sugar for any construct of the following form::
212
213 def f():
214 with cm():
215 # Do stuff
216
217 ``ContextDecorator`` lets you instead write::
218
219 @cm()
220 def f():
221 # Do stuff
222
223 It makes it clear that the ``cm`` applies to the whole function, rather than
224 just a piece of it (and saving an indentation level is nice, too).
225
Michael Foordb3a89842010-06-30 12:17:50 +0000226 Existing context managers that already have a base class can be extended by
227 using ``ContextDecorator`` as a mixin class::
228
229 from contextlib import ContextDecorator
230
231 class mycontext(ContextBaseClass, ContextDecorator):
Georg Brandl86e78d12010-07-18 13:43:32 +0000232 def __enter__(self):
233 return self
Michael Foordb3a89842010-06-30 12:17:50 +0000234
Georg Brandl86e78d12010-07-18 13:43:32 +0000235 def __exit__(self, *exc):
236 return False
Michael Foordb3a89842010-06-30 12:17:50 +0000237
Nick Coghlan0ded3e32011-05-05 23:49:25 +1000238 .. note::
239 As the decorated function must be able to be called multiple times, the
240 underlying context manager must support use in multiple :keyword:`with`
241 statements. If this is not the case, then the original construct with the
242 explicit :keyword:`with` statement inside the function should be used.
243
Michael Foordb3a89842010-06-30 12:17:50 +0000244 .. versionadded:: 3.2
245
246
Nick Coghlan3267a302012-05-21 22:54:43 +1000247.. class:: ExitStack()
248
249 A context manager that is designed to make it easy to programmatically
250 combine other context managers and cleanup functions, especially those
251 that are optional or otherwise driven by input data.
252
253 For example, a set of files may easily be handled in a single with
254 statement as follows::
255
256 with ExitStack() as stack:
257 files = [stack.enter_context(open(fname)) for fname in filenames]
258 # All opened files will automatically be closed at the end of
259 # the with statement, even if attempts to open files later
Andrew Svetlov5b898402012-12-18 21:26:36 +0200260 # in the list raise an exception
Nick Coghlan3267a302012-05-21 22:54:43 +1000261
262 Each instance maintains a stack of registered callbacks that are called in
263 reverse order when the instance is closed (either explicitly or implicitly
Nick Coghlan27228272012-05-31 22:17:08 +1000264 at the end of a :keyword:`with` statement). Note that callbacks are *not*
265 invoked implicitly when the context stack instance is garbage collected.
Nick Coghlan3267a302012-05-21 22:54:43 +1000266
267 This stack model is used so that context managers that acquire their
268 resources in their ``__init__`` method (such as file objects) can be
269 handled correctly.
270
271 Since registered callbacks are invoked in the reverse order of
Nick Coghlan27228272012-05-31 22:17:08 +1000272 registration, this ends up behaving as if multiple nested :keyword:`with`
Nick Coghlan3267a302012-05-21 22:54:43 +1000273 statements had been used with the registered set of callbacks. This even
274 extends to exception handling - if an inner callback suppresses or replaces
275 an exception, then outer callbacks will be passed arguments based on that
276 updated state.
277
278 This is a relatively low level API that takes care of the details of
279 correctly unwinding the stack of exit callbacks. It provides a suitable
280 foundation for higher level context managers that manipulate the exit
281 stack in application specific ways.
282
Nick Coghlana497b442012-05-22 23:02:00 +1000283 .. versionadded:: 3.3
284
Nick Coghlan3267a302012-05-21 22:54:43 +1000285 .. method:: enter_context(cm)
286
287 Enters a new context manager and adds its :meth:`__exit__` method to
288 the callback stack. The return value is the result of the context
289 manager's own :meth:`__enter__` method.
290
291 These context managers may suppress exceptions just as they normally
Nick Coghlan27228272012-05-31 22:17:08 +1000292 would if used directly as part of a :keyword:`with` statement.
Nick Coghlan3267a302012-05-21 22:54:43 +1000293
294 .. method:: push(exit)
295
296 Adds a context manager's :meth:`__exit__` method to the callback stack.
297
298 As ``__enter__`` is *not* invoked, this method can be used to cover
299 part of an :meth:`__enter__` implementation with a context manager's own
300 :meth:`__exit__` method.
301
302 If passed an object that is not a context manager, this method assumes
303 it is a callback with the same signature as a context manager's
304 :meth:`__exit__` method and adds it directly to the callback stack.
305
306 By returning true values, these callbacks can suppress exceptions the
307 same way context manager :meth:`__exit__` methods can.
308
309 The passed in object is returned from the function, allowing this
Nick Coghlan27228272012-05-31 22:17:08 +1000310 method to be used as a function decorator.
Nick Coghlan3267a302012-05-21 22:54:43 +1000311
312 .. method:: callback(callback, *args, **kwds)
313
314 Accepts an arbitrary callback function and arguments and adds it to
315 the callback stack.
316
317 Unlike the other methods, callbacks added this way cannot suppress
318 exceptions (as they are never passed the exception details).
319
320 The passed in callback is returned from the function, allowing this
Nick Coghlan27228272012-05-31 22:17:08 +1000321 method to be used as a function decorator.
Nick Coghlan3267a302012-05-21 22:54:43 +1000322
323 .. method:: pop_all()
324
325 Transfers the callback stack to a fresh :class:`ExitStack` instance
326 and returns it. No callbacks are invoked by this operation - instead,
327 they will now be invoked when the new stack is closed (either
Nick Coghlan27228272012-05-31 22:17:08 +1000328 explicitly or implicitly at the end of a :keyword:`with` statement).
Nick Coghlan3267a302012-05-21 22:54:43 +1000329
330 For example, a group of files can be opened as an "all or nothing"
331 operation as follows::
332
333 with ExitStack() as stack:
334 files = [stack.enter_context(open(fname)) for fname in filenames]
Barry Warsawd8f870d2013-05-10 11:35:38 -0400335 # Hold onto the close method, but don't call it yet.
336 close_files = stack.pop_all().close
Nick Coghlan3267a302012-05-21 22:54:43 +1000337 # If opening any file fails, all previously opened files will be
338 # closed automatically. If all files are opened successfully,
339 # they will remain open even after the with statement ends.
Barry Warsawd8f870d2013-05-10 11:35:38 -0400340 # close_files() can then be invoked explicitly to close them all.
Nick Coghlan3267a302012-05-21 22:54:43 +1000341
342 .. method:: close()
343
344 Immediately unwinds the callback stack, invoking callbacks in the
345 reverse order of registration. For any context managers and exit
346 callbacks registered, the arguments passed in will indicate that no
347 exception occurred.
348
Nick Coghlan3267a302012-05-21 22:54:43 +1000349
350Examples and Recipes
351--------------------
352
353This section describes some examples and recipes for making effective use of
354the tools provided by :mod:`contextlib`.
355
356
Nick Coghlan27228272012-05-31 22:17:08 +1000357Supporting a variable number of context managers
358^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
359
360The primary use case for :class:`ExitStack` is the one given in the class
361documentation: supporting a variable number of context managers and other
362cleanup operations in a single :keyword:`with` statement. The variability
363may come from the number of context managers needed being driven by user
364input (such as opening a user specified collection of files), or from
365some of the context managers being optional::
366
367 with ExitStack() as stack:
368 for resource in resources:
369 stack.enter_context(resource)
370 if need_special resource:
371 special = acquire_special_resource()
372 stack.callback(release_special_resource, special)
373 # Perform operations that use the acquired resources
374
375As shown, :class:`ExitStack` also makes it quite easy to use :keyword:`with`
376statements to manage arbitrary resources that don't natively support the
377context management protocol.
378
379
380Simplifying support for single optional context managers
381^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
382
383In the specific case of a single optional context manager, :class:`ExitStack`
384instances can be used as a "do nothing" context manager, allowing a context
Nick Coghlanb7a455f2012-05-31 22:34:59 +1000385manager to easily be omitted without affecting the overall structure of
Nick Coghlan27228272012-05-31 22:17:08 +1000386the source code::
387
388 def debug_trace(details):
389 if __debug__:
390 return TraceContext(details)
391 # Don't do anything special with the context in release mode
392 return ExitStack()
393
394 with debug_trace():
395 # Suite is traced in debug mode, but runs normally otherwise
396
397
398Catching exceptions from ``__enter__`` methods
399^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
400
401It is occasionally desirable to catch exceptions from an ``__enter__``
402method implementation, *without* inadvertently catching exceptions from
403the :keyword:`with` statement body or the context manager's ``__exit__``
404method. By using :class:`ExitStack` the steps in the context management
405protocol can be separated slightly in order to allow this::
406
407 stack = ExitStack()
408 try:
409 x = stack.enter_context(cm)
410 except Exception:
411 # handle __enter__ exception
412 else:
413 with stack:
414 # Handle normal case
415
416Actually needing to do this is likely to indicate that the underlying API
417should be providing a direct resource management interface for use with
418:keyword:`try`/:keyword:`except`/:keyword:`finally` statements, but not
419all APIs are well designed in that regard. When a context manager is the
420only resource management API provided, then :class:`ExitStack` can make it
421easier to handle various situations that can't be handled directly in a
422:keyword:`with` statement.
423
424
Nick Coghlan3267a302012-05-21 22:54:43 +1000425Cleaning up in an ``__enter__`` implementation
426^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
427
428As noted in the documentation of :meth:`ExitStack.push`, this
429method can be useful in cleaning up an already allocated resource if later
430steps in the :meth:`__enter__` implementation fail.
431
432Here's an example of doing this for a context manager that accepts resource
433acquisition and release functions, along with an optional validation function,
434and maps them to the context management protocol::
435
436 from contextlib import contextmanager, ExitStack
437
Ezio Melottic9cfcf12013-03-11 09:42:40 +0200438 class ResourceManager:
Nick Coghlan3267a302012-05-21 22:54:43 +1000439
440 def __init__(self, acquire_resource, release_resource, check_resource_ok=None):
441 self.acquire_resource = acquire_resource
442 self.release_resource = release_resource
443 if check_resource_ok is None:
444 def check_resource_ok(resource):
445 return True
446 self.check_resource_ok = check_resource_ok
447
448 @contextmanager
449 def _cleanup_on_error(self):
450 with ExitStack() as stack:
451 stack.push(self)
452 yield
453 # The validation check passed and didn't raise an exception
454 # Accordingly, we want to keep the resource, and pass it
455 # back to our caller
456 stack.pop_all()
457
458 def __enter__(self):
459 resource = self.acquire_resource()
460 with self._cleanup_on_error():
461 if not self.check_resource_ok(resource):
462 msg = "Failed validation for {!r}"
463 raise RuntimeError(msg.format(resource))
464 return resource
465
466 def __exit__(self, *exc_details):
467 # We don't need to duplicate any of our resource release logic
468 self.release_resource()
469
470
471Replacing any use of ``try-finally`` and flag variables
472^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
473
474A pattern you will sometimes see is a ``try-finally`` statement with a flag
475variable to indicate whether or not the body of the ``finally`` clause should
476be executed. In its simplest form (that can't already be handled just by
477using an ``except`` clause instead), it looks something like this::
478
479 cleanup_needed = True
480 try:
481 result = perform_operation()
482 if result:
483 cleanup_needed = False
484 finally:
485 if cleanup_needed:
486 cleanup_resources()
487
488As with any ``try`` statement based code, this can cause problems for
489development and review, because the setup code and the cleanup code can end
490up being separated by arbitrarily long sections of code.
491
492:class:`ExitStack` makes it possible to instead register a callback for
493execution at the end of a ``with`` statement, and then later decide to skip
494executing that callback::
495
496 from contextlib import ExitStack
497
498 with ExitStack() as stack:
499 stack.callback(cleanup_resources)
500 result = perform_operation()
501 if result:
502 stack.pop_all()
503
504This allows the intended cleanup up behaviour to be made explicit up front,
505rather than requiring a separate flag variable.
506
507If a particular application uses this pattern a lot, it can be simplified
508even further by means of a small helper class::
509
510 from contextlib import ExitStack
511
512 class Callback(ExitStack):
513 def __init__(self, callback, *args, **kwds):
514 super(Callback, self).__init__()
515 self.callback(callback, *args, **kwds)
516
517 def cancel(self):
518 self.pop_all()
519
520 with Callback(cleanup_resources) as cb:
521 result = perform_operation()
522 if result:
523 cb.cancel()
524
525If the resource cleanup isn't already neatly bundled into a standalone
526function, then it is still possible to use the decorator form of
527:meth:`ExitStack.callback` to declare the resource cleanup in
528advance::
529
530 from contextlib import ExitStack
531
532 with ExitStack() as stack:
533 @stack.callback
534 def cleanup_resources():
535 ...
536 result = perform_operation()
537 if result:
538 stack.pop_all()
539
540Due to the way the decorator protocol works, a callback function
541declared this way cannot take any parameters. Instead, any resources to
542be released must be accessed as closure variables
543
544
545Using a context manager as a function decorator
546^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
547
548:class:`ContextDecorator` makes it possible to use a context manager in
549both an ordinary ``with`` statement and also as a function decorator.
550
551For example, it is sometimes useful to wrap functions or groups of statements
552with a logger that can track the time of entry and time of exit. Rather than
553writing both a function decorator and a context manager for the task,
554inheriting from :class:`ContextDecorator` provides both capabilities in a
555single definition::
556
557 from contextlib import ContextDecorator
558 import logging
559
560 logging.basicConfig(level=logging.INFO)
561
562 class track_entry_and_exit(ContextDecorator):
563 def __init__(self, name):
564 self.name = name
565
566 def __enter__(self):
567 logging.info('Entering: {}'.format(name))
568
569 def __exit__(self, exc_type, exc, exc_tb):
570 logging.info('Exiting: {}'.format(name))
571
572Instances of this class can be used as both a context manager::
573
574 with track_entry_and_exit('widget loader'):
575 print('Some time consuming activity goes here')
576 load_widget()
577
578And also as a function decorator::
579
580 @track_entry_and_exit('widget loader')
581 def activity():
582 print('Some time consuming activity goes here')
583 load_widget()
584
585Note that there is one additional limitation when using context managers
586as function decorators: there's no way to access the return value of
587:meth:`__enter__`. If that value is needed, then it is still necessary to use
588an explicit ``with`` statement.
589
Georg Brandl116aa622007-08-15 14:28:22 +0000590.. seealso::
591
592 :pep:`0343` - The "with" statement
593 The specification, background, and examples for the Python :keyword:`with`
594 statement.
595