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