1:mod:`!contextlib` --- Utilities for :keyword:`!with`\ -statement contexts 2========================================================================== 3 4.. module:: contextlib 5 :synopsis: Utilities for with-statement contexts. 6 7**Source code:** :source:`Lib/contextlib.py` 8 9-------------- 10 11This module provides utilities for common tasks involving the :keyword:`with` 12statement. For more information see also :ref:`typecontextmanager` and 13:ref:`context-managers`. 14 15 16Utilities 17--------- 18 19Functions and classes provided: 20 21.. class:: AbstractContextManager 22 23 An :term:`abstract base class` for classes that implement 24 :meth:`object.__enter__` and :meth:`object.__exit__`. A default 25 implementation for :meth:`object.__enter__` is provided which returns 26 ``self`` while :meth:`object.__exit__` is an abstract method which by default 27 returns ``None``. See also the definition of :ref:`typecontextmanager`. 28 29 .. versionadded:: 3.6 30 31 32.. class:: AbstractAsyncContextManager 33 34 An :term:`abstract base class` for classes that implement 35 :meth:`object.__aenter__` and :meth:`object.__aexit__`. A default 36 implementation for :meth:`object.__aenter__` is provided which returns 37 ``self`` while :meth:`object.__aexit__` is an abstract method which by default 38 returns ``None``. See also the definition of 39 :ref:`async-context-managers`. 40 41 .. versionadded:: 3.7 42 43 44.. decorator:: contextmanager 45 46 This function is a :term:`decorator` that can be used to define a factory 47 function for :keyword:`with` statement context managers, without needing to 48 create a class or separate :meth:`__enter__` and :meth:`__exit__` methods. 49 50 While many objects natively support use in with statements, sometimes a 51 resource needs to be managed that isn't a context manager in its own right, 52 and doesn't implement a ``close()`` method for use with ``contextlib.closing`` 53 54 An abstract example would be the following to ensure correct resource 55 management:: 56 57 from contextlib import contextmanager 58 59 @contextmanager 60 def managed_resource(*args, **kwds): 61 # Code to acquire resource, e.g.: 62 resource = acquire_resource(*args, **kwds) 63 try: 64 yield resource 65 finally: 66 # Code to release resource, e.g.: 67 release_resource(resource) 68 69 >>> with managed_resource(timeout=3600) as resource: 70 ... # Resource is released at the end of this block, 71 ... # even if code in the block raises an exception 72 73 The function being decorated must return a :term:`generator`-iterator when 74 called. This iterator must yield exactly one value, which will be bound to 75 the targets in the :keyword:`with` statement's :keyword:`!as` clause, if any. 76 77 At the point where the generator yields, the block nested in the :keyword:`with` 78 statement is executed. The generator is then resumed after the block is exited. 79 If an unhandled exception occurs in the block, it is reraised inside the 80 generator at the point where the yield occurred. Thus, you can use a 81 :keyword:`try`...\ :keyword:`except`...\ :keyword:`finally` statement to trap 82 the error (if any), or ensure that some cleanup takes place. If an exception is 83 trapped merely in order to log it or to perform some action (rather than to 84 suppress it entirely), the generator must reraise that exception. Otherwise the 85 generator context manager will indicate to the :keyword:`!with` statement that 86 the exception has been handled, and execution will resume with the statement 87 immediately following the :keyword:`!with` statement. 88 89 :func:`contextmanager` uses :class:`ContextDecorator` so the context managers 90 it creates can be used as decorators as well as in :keyword:`with` statements. 91 When used as a decorator, a new generator instance is implicitly created on 92 each function call (this allows the otherwise "one-shot" context managers 93 created by :func:`contextmanager` to meet the requirement that context 94 managers support multiple invocations in order to be used as decorators). 95 96 .. versionchanged:: 3.2 97 Use of :class:`ContextDecorator`. 98 99 100.. decorator:: asynccontextmanager 101 102 Similar to :func:`~contextlib.contextmanager`, but creates an 103 :ref:`asynchronous context manager <async-context-managers>`. 104 105 This function is a :term:`decorator` that can be used to define a factory 106 function for :keyword:`async with` statement asynchronous context managers, 107 without needing to create a class or separate :meth:`__aenter__` and 108 :meth:`__aexit__` methods. It must be applied to an :term:`asynchronous 109 generator` function. 110 111 A simple example:: 112 113 from contextlib import asynccontextmanager 114 115 @asynccontextmanager 116 async def get_connection(): 117 conn = await acquire_db_connection() 118 try: 119 yield conn 120 finally: 121 await release_db_connection(conn) 122 123 async def get_all_users(): 124 async with get_connection() as conn: 125 return conn.query('SELECT ...') 126 127 .. versionadded:: 3.7 128 129 130.. function:: closing(thing) 131 132 Return a context manager that closes *thing* upon completion of the block. This 133 is basically equivalent to:: 134 135 from contextlib import contextmanager 136 137 @contextmanager 138 def closing(thing): 139 try: 140 yield thing 141 finally: 142 thing.close() 143 144 And lets you write code like this:: 145 146 from contextlib import closing 147 from urllib.request import urlopen 148 149 with closing(urlopen('http://www.python.org')) as page: 150 for line in page: 151 print(line) 152 153 without needing to explicitly close ``page``. Even if an error occurs, 154 ``page.close()`` will be called when the :keyword:`with` block is exited. 155 156 157.. _simplifying-support-for-single-optional-context-managers: 158 159.. function:: nullcontext(enter_result=None) 160 161 Return a context manager that returns *enter_result* from ``__enter__``, but 162 otherwise does nothing. It is intended to be used as a stand-in for an 163 optional context manager, for example:: 164 165 def myfunction(arg, ignore_exceptions=False): 166 if ignore_exceptions: 167 # Use suppress to ignore all exceptions. 168 cm = contextlib.suppress(Exception) 169 else: 170 # Do not ignore any exceptions, cm has no effect. 171 cm = contextlib.nullcontext() 172 with cm: 173 # Do something 174 175 An example using *enter_result*:: 176 177 def process_file(file_or_path): 178 if isinstance(file_or_path, str): 179 # If string, open file 180 cm = open(file_or_path) 181 else: 182 # Caller is responsible for closing file 183 cm = nullcontext(file_or_path) 184 185 with cm as file: 186 # Perform processing on the file 187 188 .. versionadded:: 3.7 189 190 191.. function:: suppress(*exceptions) 192 193 Return a context manager that suppresses any of the specified exceptions 194 if they occur in the body of a with statement and then resumes execution 195 with the first statement following the end of the with statement. 196 197 As with any other mechanism that completely suppresses exceptions, this 198 context manager should be used only to cover very specific errors where 199 silently continuing with program execution is known to be the right 200 thing to do. 201 202 For example:: 203 204 from contextlib import suppress 205 206 with suppress(FileNotFoundError): 207 os.remove('somefile.tmp') 208 209 with suppress(FileNotFoundError): 210 os.remove('someotherfile.tmp') 211 212 This code is equivalent to:: 213 214 try: 215 os.remove('somefile.tmp') 216 except FileNotFoundError: 217 pass 218 219 try: 220 os.remove('someotherfile.tmp') 221 except FileNotFoundError: 222 pass 223 224 This context manager is :ref:`reentrant <reentrant-cms>`. 225 226 .. versionadded:: 3.4 227 228 229.. function:: redirect_stdout(new_target) 230 231 Context manager for temporarily redirecting :data:`sys.stdout` to 232 another file or file-like object. 233 234 This tool adds flexibility to existing functions or classes whose output 235 is hardwired to stdout. 236 237 For example, the output of :func:`help` normally is sent to *sys.stdout*. 238 You can capture that output in a string by redirecting the output to an 239 :class:`io.StringIO` object:: 240 241 f = io.StringIO() 242 with redirect_stdout(f): 243 help(pow) 244 s = f.getvalue() 245 246 To send the output of :func:`help` to a file on disk, redirect the output 247 to a regular file:: 248 249 with open('help.txt', 'w') as f: 250 with redirect_stdout(f): 251 help(pow) 252 253 To send the output of :func:`help` to *sys.stderr*:: 254 255 with redirect_stdout(sys.stderr): 256 help(pow) 257 258 Note that the global side effect on :data:`sys.stdout` means that this 259 context manager is not suitable for use in library code and most threaded 260 applications. It also has no effect on the output of subprocesses. 261 However, it is still a useful approach for many utility scripts. 262 263 This context manager is :ref:`reentrant <reentrant-cms>`. 264 265 .. versionadded:: 3.4 266 267 268.. function:: redirect_stderr(new_target) 269 270 Similar to :func:`~contextlib.redirect_stdout` but redirecting 271 :data:`sys.stderr` to another file or file-like object. 272 273 This context manager is :ref:`reentrant <reentrant-cms>`. 274 275 .. versionadded:: 3.5 276 277 278.. class:: ContextDecorator() 279 280 A base class that enables a context manager to also be used as a decorator. 281 282 Context managers inheriting from ``ContextDecorator`` have to implement 283 ``__enter__`` and ``__exit__`` as normal. ``__exit__`` retains its optional 284 exception handling even when used as a decorator. 285 286 ``ContextDecorator`` is used by :func:`contextmanager`, so you get this 287 functionality automatically. 288 289 Example of ``ContextDecorator``:: 290 291 from contextlib import ContextDecorator 292 293 class mycontext(ContextDecorator): 294 def __enter__(self): 295 print('Starting') 296 return self 297 298 def __exit__(self, *exc): 299 print('Finishing') 300 return False 301 302 >>> @mycontext() 303 ... def function(): 304 ... print('The bit in the middle') 305 ... 306 >>> function() 307 Starting 308 The bit in the middle 309 Finishing 310 311 >>> with mycontext(): 312 ... print('The bit in the middle') 313 ... 314 Starting 315 The bit in the middle 316 Finishing 317 318 This change is just syntactic sugar for any construct of the following form:: 319 320 def f(): 321 with cm(): 322 # Do stuff 323 324 ``ContextDecorator`` lets you instead write:: 325 326 @cm() 327 def f(): 328 # Do stuff 329 330 It makes it clear that the ``cm`` applies to the whole function, rather than 331 just a piece of it (and saving an indentation level is nice, too). 332 333 Existing context managers that already have a base class can be extended by 334 using ``ContextDecorator`` as a mixin class:: 335 336 from contextlib import ContextDecorator 337 338 class mycontext(ContextBaseClass, ContextDecorator): 339 def __enter__(self): 340 return self 341 342 def __exit__(self, *exc): 343 return False 344 345 .. note:: 346 As the decorated function must be able to be called multiple times, the 347 underlying context manager must support use in multiple :keyword:`with` 348 statements. If this is not the case, then the original construct with the 349 explicit :keyword:`!with` statement inside the function should be used. 350 351 .. versionadded:: 3.2 352 353 354.. class:: ExitStack() 355 356 A context manager that is designed to make it easy to programmatically 357 combine other context managers and cleanup functions, especially those 358 that are optional or otherwise driven by input data. 359 360 For example, a set of files may easily be handled in a single with 361 statement as follows:: 362 363 with ExitStack() as stack: 364 files = [stack.enter_context(open(fname)) for fname in filenames] 365 # All opened files will automatically be closed at the end of 366 # the with statement, even if attempts to open files later 367 # in the list raise an exception 368 369 Each instance maintains a stack of registered callbacks that are called in 370 reverse order when the instance is closed (either explicitly or implicitly 371 at the end of a :keyword:`with` statement). Note that callbacks are *not* 372 invoked implicitly when the context stack instance is garbage collected. 373 374 This stack model is used so that context managers that acquire their 375 resources in their ``__init__`` method (such as file objects) can be 376 handled correctly. 377 378 Since registered callbacks are invoked in the reverse order of 379 registration, this ends up behaving as if multiple nested :keyword:`with` 380 statements had been used with the registered set of callbacks. This even 381 extends to exception handling - if an inner callback suppresses or replaces 382 an exception, then outer callbacks will be passed arguments based on that 383 updated state. 384 385 This is a relatively low level API that takes care of the details of 386 correctly unwinding the stack of exit callbacks. It provides a suitable 387 foundation for higher level context managers that manipulate the exit 388 stack in application specific ways. 389 390 .. versionadded:: 3.3 391 392 .. method:: enter_context(cm) 393 394 Enters a new context manager and adds its :meth:`__exit__` method to 395 the callback stack. The return value is the result of the context 396 manager's own :meth:`__enter__` method. 397 398 These context managers may suppress exceptions just as they normally 399 would if used directly as part of a :keyword:`with` statement. 400 401 .. method:: push(exit) 402 403 Adds a context manager's :meth:`__exit__` method to the callback stack. 404 405 As ``__enter__`` is *not* invoked, this method can be used to cover 406 part of an :meth:`__enter__` implementation with a context manager's own 407 :meth:`__exit__` method. 408 409 If passed an object that is not a context manager, this method assumes 410 it is a callback with the same signature as a context manager's 411 :meth:`__exit__` method and adds it directly to the callback stack. 412 413 By returning true values, these callbacks can suppress exceptions the 414 same way context manager :meth:`__exit__` methods can. 415 416 The passed in object is returned from the function, allowing this 417 method to be used as a function decorator. 418 419 .. method:: callback(callback, /, *args, **kwds) 420 421 Accepts an arbitrary callback function and arguments and adds it to 422 the callback stack. 423 424 Unlike the other methods, callbacks added this way cannot suppress 425 exceptions (as they are never passed the exception details). 426 427 The passed in callback is returned from the function, allowing this 428 method to be used as a function decorator. 429 430 .. method:: pop_all() 431 432 Transfers the callback stack to a fresh :class:`ExitStack` instance 433 and returns it. No callbacks are invoked by this operation - instead, 434 they will now be invoked when the new stack is closed (either 435 explicitly or implicitly at the end of a :keyword:`with` statement). 436 437 For example, a group of files can be opened as an "all or nothing" 438 operation as follows:: 439 440 with ExitStack() as stack: 441 files = [stack.enter_context(open(fname)) for fname in filenames] 442 # Hold onto the close method, but don't call it yet. 443 close_files = stack.pop_all().close 444 # If opening any file fails, all previously opened files will be 445 # closed automatically. If all files are opened successfully, 446 # they will remain open even after the with statement ends. 447 # close_files() can then be invoked explicitly to close them all. 448 449 .. method:: close() 450 451 Immediately unwinds the callback stack, invoking callbacks in the 452 reverse order of registration. For any context managers and exit 453 callbacks registered, the arguments passed in will indicate that no 454 exception occurred. 455 456.. class:: AsyncExitStack() 457 458 An :ref:`asynchronous context manager <async-context-managers>`, similar 459 to :class:`ExitStack`, that supports combining both synchronous and 460 asynchronous context managers, as well as having coroutines for 461 cleanup logic. 462 463 The :meth:`close` method is not implemented, :meth:`aclose` must be used 464 instead. 465 466 .. method:: enter_async_context(cm) 467 468 Similar to :meth:`enter_context` but expects an asynchronous context 469 manager. 470 471 .. method:: push_async_exit(exit) 472 473 Similar to :meth:`push` but expects either an asynchronous context manager 474 or a coroutine function. 475 476 .. method:: push_async_callback(callback, /, *args, **kwds) 477 478 Similar to :meth:`callback` but expects a coroutine function. 479 480 .. method:: aclose() 481 482 Similar to :meth:`close` but properly handles awaitables. 483 484 Continuing the example for :func:`asynccontextmanager`:: 485 486 async with AsyncExitStack() as stack: 487 connections = [await stack.enter_async_context(get_connection()) 488 for i in range(5)] 489 # All opened connections will automatically be released at the end of 490 # the async with statement, even if attempts to open a connection 491 # later in the list raise an exception. 492 493 .. versionadded:: 3.7 494 495Examples and Recipes 496-------------------- 497 498This section describes some examples and recipes for making effective use of 499the tools provided by :mod:`contextlib`. 500 501 502Supporting a variable number of context managers 503^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 504 505The primary use case for :class:`ExitStack` is the one given in the class 506documentation: supporting a variable number of context managers and other 507cleanup operations in a single :keyword:`with` statement. The variability 508may come from the number of context managers needed being driven by user 509input (such as opening a user specified collection of files), or from 510some of the context managers being optional:: 511 512 with ExitStack() as stack: 513 for resource in resources: 514 stack.enter_context(resource) 515 if need_special_resource(): 516 special = acquire_special_resource() 517 stack.callback(release_special_resource, special) 518 # Perform operations that use the acquired resources 519 520As shown, :class:`ExitStack` also makes it quite easy to use :keyword:`with` 521statements to manage arbitrary resources that don't natively support the 522context management protocol. 523 524 525Catching exceptions from ``__enter__`` methods 526^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 527 528It is occasionally desirable to catch exceptions from an ``__enter__`` 529method implementation, *without* inadvertently catching exceptions from 530the :keyword:`with` statement body or the context manager's ``__exit__`` 531method. By using :class:`ExitStack` the steps in the context management 532protocol can be separated slightly in order to allow this:: 533 534 stack = ExitStack() 535 try: 536 x = stack.enter_context(cm) 537 except Exception: 538 # handle __enter__ exception 539 else: 540 with stack: 541 # Handle normal case 542 543Actually needing to do this is likely to indicate that the underlying API 544should be providing a direct resource management interface for use with 545:keyword:`try`/:keyword:`except`/:keyword:`finally` statements, but not 546all APIs are well designed in that regard. When a context manager is the 547only resource management API provided, then :class:`ExitStack` can make it 548easier to handle various situations that can't be handled directly in a 549:keyword:`with` statement. 550 551 552Cleaning up in an ``__enter__`` implementation 553^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 554 555As noted in the documentation of :meth:`ExitStack.push`, this 556method can be useful in cleaning up an already allocated resource if later 557steps in the :meth:`__enter__` implementation fail. 558 559Here's an example of doing this for a context manager that accepts resource 560acquisition and release functions, along with an optional validation function, 561and maps them to the context management protocol:: 562 563 from contextlib import contextmanager, AbstractContextManager, ExitStack 564 565 class ResourceManager(AbstractContextManager): 566 567 def __init__(self, acquire_resource, release_resource, check_resource_ok=None): 568 self.acquire_resource = acquire_resource 569 self.release_resource = release_resource 570 if check_resource_ok is None: 571 def check_resource_ok(resource): 572 return True 573 self.check_resource_ok = check_resource_ok 574 575 @contextmanager 576 def _cleanup_on_error(self): 577 with ExitStack() as stack: 578 stack.push(self) 579 yield 580 # The validation check passed and didn't raise an exception 581 # Accordingly, we want to keep the resource, and pass it 582 # back to our caller 583 stack.pop_all() 584 585 def __enter__(self): 586 resource = self.acquire_resource() 587 with self._cleanup_on_error(): 588 if not self.check_resource_ok(resource): 589 msg = "Failed validation for {!r}" 590 raise RuntimeError(msg.format(resource)) 591 return resource 592 593 def __exit__(self, *exc_details): 594 # We don't need to duplicate any of our resource release logic 595 self.release_resource() 596 597 598Replacing any use of ``try-finally`` and flag variables 599^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 600 601A pattern you will sometimes see is a ``try-finally`` statement with a flag 602variable to indicate whether or not the body of the ``finally`` clause should 603be executed. In its simplest form (that can't already be handled just by 604using an ``except`` clause instead), it looks something like this:: 605 606 cleanup_needed = True 607 try: 608 result = perform_operation() 609 if result: 610 cleanup_needed = False 611 finally: 612 if cleanup_needed: 613 cleanup_resources() 614 615As with any ``try`` statement based code, this can cause problems for 616development and review, because the setup code and the cleanup code can end 617up being separated by arbitrarily long sections of code. 618 619:class:`ExitStack` makes it possible to instead register a callback for 620execution at the end of a ``with`` statement, and then later decide to skip 621executing that callback:: 622 623 from contextlib import ExitStack 624 625 with ExitStack() as stack: 626 stack.callback(cleanup_resources) 627 result = perform_operation() 628 if result: 629 stack.pop_all() 630 631This allows the intended cleanup up behaviour to be made explicit up front, 632rather than requiring a separate flag variable. 633 634If a particular application uses this pattern a lot, it can be simplified 635even further by means of a small helper class:: 636 637 from contextlib import ExitStack 638 639 class Callback(ExitStack): 640 def __init__(self, callback, /, *args, **kwds): 641 super(Callback, self).__init__() 642 self.callback(callback, *args, **kwds) 643 644 def cancel(self): 645 self.pop_all() 646 647 with Callback(cleanup_resources) as cb: 648 result = perform_operation() 649 if result: 650 cb.cancel() 651 652If the resource cleanup isn't already neatly bundled into a standalone 653function, then it is still possible to use the decorator form of 654:meth:`ExitStack.callback` to declare the resource cleanup in 655advance:: 656 657 from contextlib import ExitStack 658 659 with ExitStack() as stack: 660 @stack.callback 661 def cleanup_resources(): 662 ... 663 result = perform_operation() 664 if result: 665 stack.pop_all() 666 667Due to the way the decorator protocol works, a callback function 668declared this way cannot take any parameters. Instead, any resources to 669be released must be accessed as closure variables. 670 671 672Using a context manager as a function decorator 673^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 674 675:class:`ContextDecorator` makes it possible to use a context manager in 676both an ordinary ``with`` statement and also as a function decorator. 677 678For example, it is sometimes useful to wrap functions or groups of statements 679with a logger that can track the time of entry and time of exit. Rather than 680writing both a function decorator and a context manager for the task, 681inheriting from :class:`ContextDecorator` provides both capabilities in a 682single definition:: 683 684 from contextlib import ContextDecorator 685 import logging 686 687 logging.basicConfig(level=logging.INFO) 688 689 class track_entry_and_exit(ContextDecorator): 690 def __init__(self, name): 691 self.name = name 692 693 def __enter__(self): 694 logging.info('Entering: %s', self.name) 695 696 def __exit__(self, exc_type, exc, exc_tb): 697 logging.info('Exiting: %s', self.name) 698 699Instances of this class can be used as both a context manager:: 700 701 with track_entry_and_exit('widget loader'): 702 print('Some time consuming activity goes here') 703 load_widget() 704 705And also as a function decorator:: 706 707 @track_entry_and_exit('widget loader') 708 def activity(): 709 print('Some time consuming activity goes here') 710 load_widget() 711 712Note that there is one additional limitation when using context managers 713as function decorators: there's no way to access the return value of 714:meth:`__enter__`. If that value is needed, then it is still necessary to use 715an explicit ``with`` statement. 716 717.. seealso:: 718 719 :pep:`343` - The "with" statement 720 The specification, background, and examples for the Python :keyword:`with` 721 statement. 722 723.. _single-use-reusable-and-reentrant-cms: 724 725Single use, reusable and reentrant context managers 726--------------------------------------------------- 727 728Most context managers are written in a way that means they can only be 729used effectively in a :keyword:`with` statement once. These single use 730context managers must be created afresh each time they're used - 731attempting to use them a second time will trigger an exception or 732otherwise not work correctly. 733 734This common limitation means that it is generally advisable to create 735context managers directly in the header of the :keyword:`with` statement 736where they are used (as shown in all of the usage examples above). 737 738Files are an example of effectively single use context managers, since 739the first :keyword:`with` statement will close the file, preventing any 740further IO operations using that file object. 741 742Context managers created using :func:`contextmanager` are also single use 743context managers, and will complain about the underlying generator failing 744to yield if an attempt is made to use them a second time:: 745 746 >>> from contextlib import contextmanager 747 >>> @contextmanager 748 ... def singleuse(): 749 ... print("Before") 750 ... yield 751 ... print("After") 752 ... 753 >>> cm = singleuse() 754 >>> with cm: 755 ... pass 756 ... 757 Before 758 After 759 >>> with cm: 760 ... pass 761 ... 762 Traceback (most recent call last): 763 ... 764 RuntimeError: generator didn't yield 765 766 767.. _reentrant-cms: 768 769Reentrant context managers 770^^^^^^^^^^^^^^^^^^^^^^^^^^ 771 772More sophisticated context managers may be "reentrant". These context 773managers can not only be used in multiple :keyword:`with` statements, 774but may also be used *inside* a :keyword:`!with` statement that is already 775using the same context manager. 776 777:class:`threading.RLock` is an example of a reentrant context manager, as are 778:func:`suppress` and :func:`redirect_stdout`. Here's a very simple example of 779reentrant use:: 780 781 >>> from contextlib import redirect_stdout 782 >>> from io import StringIO 783 >>> stream = StringIO() 784 >>> write_to_stream = redirect_stdout(stream) 785 >>> with write_to_stream: 786 ... print("This is written to the stream rather than stdout") 787 ... with write_to_stream: 788 ... print("This is also written to the stream") 789 ... 790 >>> print("This is written directly to stdout") 791 This is written directly to stdout 792 >>> print(stream.getvalue()) 793 This is written to the stream rather than stdout 794 This is also written to the stream 795 796Real world examples of reentrancy are more likely to involve multiple 797functions calling each other and hence be far more complicated than this 798example. 799 800Note also that being reentrant is *not* the same thing as being thread safe. 801:func:`redirect_stdout`, for example, is definitely not thread safe, as it 802makes a global modification to the system state by binding :data:`sys.stdout` 803to a different stream. 804 805 806.. _reusable-cms: 807 808Reusable context managers 809^^^^^^^^^^^^^^^^^^^^^^^^^ 810 811Distinct from both single use and reentrant context managers are "reusable" 812context managers (or, to be completely explicit, "reusable, but not 813reentrant" context managers, since reentrant context managers are also 814reusable). These context managers support being used multiple times, but 815will fail (or otherwise not work correctly) if the specific context manager 816instance has already been used in a containing with statement. 817 818:class:`threading.Lock` is an example of a reusable, but not reentrant, 819context manager (for a reentrant lock, it is necessary to use 820:class:`threading.RLock` instead). 821 822Another example of a reusable, but not reentrant, context manager is 823:class:`ExitStack`, as it invokes *all* currently registered callbacks 824when leaving any with statement, regardless of where those callbacks 825were added:: 826 827 >>> from contextlib import ExitStack 828 >>> stack = ExitStack() 829 >>> with stack: 830 ... stack.callback(print, "Callback: from first context") 831 ... print("Leaving first context") 832 ... 833 Leaving first context 834 Callback: from first context 835 >>> with stack: 836 ... stack.callback(print, "Callback: from second context") 837 ... print("Leaving second context") 838 ... 839 Leaving second context 840 Callback: from second context 841 >>> with stack: 842 ... stack.callback(print, "Callback: from outer context") 843 ... with stack: 844 ... stack.callback(print, "Callback: from inner context") 845 ... print("Leaving inner context") 846 ... print("Leaving outer context") 847 ... 848 Leaving inner context 849 Callback: from inner context 850 Callback: from outer context 851 Leaving outer context 852 853As the output from the example shows, reusing a single stack object across 854multiple with statements works correctly, but attempting to nest them 855will cause the stack to be cleared at the end of the innermost with 856statement, which is unlikely to be desirable behaviour. 857 858Using separate :class:`ExitStack` instances instead of reusing a single 859instance avoids that problem:: 860 861 >>> from contextlib import ExitStack 862 >>> with ExitStack() as outer_stack: 863 ... outer_stack.callback(print, "Callback: from outer context") 864 ... with ExitStack() as inner_stack: 865 ... inner_stack.callback(print, "Callback: from inner context") 866 ... print("Leaving inner context") 867 ... print("Leaving outer context") 868 ... 869 Leaving inner context 870 Callback: from inner context 871 Leaving outer context 872 Callback: from outer context 873