summaryrefslogtreecommitdiffstats
path: root/Doc
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2012-05-31 12:17:08 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2012-05-31 12:17:08 (GMT)
commit272282707153ef18a1f57f962590945fe338d820 (patch)
tree8b843296fc8f34a6e0256482e3881ceadb7054c7 /Doc
parent48c2e4d0c248619e651c0a0124cbce10bb9d2d13 (diff)
downloadcpython-272282707153ef18a1f57f962590945fe338d820.zip
cpython-272282707153ef18a1f57f962590945fe338d820.tar.gz
cpython-272282707153ef18a1f57f962590945fe338d820.tar.bz2
Additional ExitStack examples, and a few other cleanups for the ExitStack docs
Diffstat (limited to 'Doc')
-rw-r--r--Doc/library/contextlib.rst82
1 files changed, 75 insertions, 7 deletions
diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst
index b1bfa18..527032d 100644
--- a/Doc/library/contextlib.rst
+++ b/Doc/library/contextlib.rst
@@ -188,15 +188,15 @@ Functions and classes provided:
Each instance maintains a stack of registered callbacks that are called in
reverse order when the instance is closed (either explicitly or implicitly
- at the end of a ``with`` statement). Note that callbacks are *not* invoked
- implicitly when the context stack instance is garbage collected.
+ at the end of a :keyword:`with` statement). Note that callbacks are *not*
+ invoked implicitly when the context stack instance is garbage collected.
This stack model is used so that context managers that acquire their
resources in their ``__init__`` method (such as file objects) can be
handled correctly.
Since registered callbacks are invoked in the reverse order of
- registration, this ends up behaving as if multiple nested ``with``
+ registration, this ends up behaving as if multiple nested :keyword:`with`
statements had been used with the registered set of callbacks. This even
extends to exception handling - if an inner callback suppresses or replaces
an exception, then outer callbacks will be passed arguments based on that
@@ -216,7 +216,7 @@ Functions and classes provided:
manager's own :meth:`__enter__` method.
These context managers may suppress exceptions just as they normally
- would if used directly as part of a ``with`` statement.
+ would if used directly as part of a :keyword:`with` statement.
.. method:: push(exit)
@@ -234,7 +234,7 @@ Functions and classes provided:
same way context manager :meth:`__exit__` methods can.
The passed in object is returned from the function, allowing this
- method to be used is a function decorator.
+ method to be used as a function decorator.
.. method:: callback(callback, *args, **kwds)
@@ -245,14 +245,14 @@ Functions and classes provided:
exceptions (as they are never passed the exception details).
The passed in callback is returned from the function, allowing this
- method to be used is a function decorator.
+ method to be used as a function decorator.
.. method:: pop_all()
Transfers the callback stack to a fresh :class:`ExitStack` instance
and returns it. No callbacks are invoked by this operation - instead,
they will now be invoked when the new stack is closed (either
- explicitly or implicitly).
+ explicitly or implicitly at the end of a :keyword:`with` statement).
For example, a group of files can be opened as an "all or nothing"
operation as follows::
@@ -280,6 +280,74 @@ This section describes some examples and recipes for making effective use of
the tools provided by :mod:`contextlib`.
+Supporting a variable number of context managers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The primary use case for :class:`ExitStack` is the one given in the class
+documentation: supporting a variable number of context managers and other
+cleanup operations in a single :keyword:`with` statement. The variability
+may come from the number of context managers needed being driven by user
+input (such as opening a user specified collection of files), or from
+some of the context managers being optional::
+
+ with ExitStack() as stack:
+ for resource in resources:
+ stack.enter_context(resource)
+ if need_special resource:
+ special = acquire_special_resource()
+ stack.callback(release_special_resource, special)
+ # Perform operations that use the acquired resources
+
+As shown, :class:`ExitStack` also makes it quite easy to use :keyword:`with`
+statements to manage arbitrary resources that don't natively support the
+context management protocol.
+
+
+Simplifying support for single optional context managers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In the specific case of a single optional context manager, :class:`ExitStack`
+instances can be used as a "do nothing" context manager, allowing a context
+managers to easily be omitted without affecting the overall structure of
+the source code::
+
+ def debug_trace(details):
+ if __debug__:
+ return TraceContext(details)
+ # Don't do anything special with the context in release mode
+ return ExitStack()
+
+ with debug_trace():
+ # Suite is traced in debug mode, but runs normally otherwise
+
+
+Catching exceptions from ``__enter__`` methods
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+It is occasionally desirable to catch exceptions from an ``__enter__``
+method implementation, *without* inadvertently catching exceptions from
+the :keyword:`with` statement body or the context manager's ``__exit__``
+method. By using :class:`ExitStack` the steps in the context management
+protocol can be separated slightly in order to allow this::
+
+ stack = ExitStack()
+ try:
+ x = stack.enter_context(cm)
+ except Exception:
+ # handle __enter__ exception
+ else:
+ with stack:
+ # Handle normal case
+
+Actually needing to do this is likely to indicate that the underlying API
+should be providing a direct resource management interface for use with
+:keyword:`try`/:keyword:`except`/:keyword:`finally` statements, but not
+all APIs are well designed in that regard. When a context manager is the
+only resource management API provided, then :class:`ExitStack` can make it
+easier to handle various situations that can't be handled directly in a
+:keyword:`with` statement.
+
+
Cleaning up in an ``__enter__`` implementation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^