summaryrefslogtreecommitdiffstats
path: root/Doc
diff options
context:
space:
mode:
authorAndrew M. Kuchling <amk@amk.ca>2006-04-23 21:01:04 (GMT)
committerAndrew M. Kuchling <amk@amk.ca>2006-04-23 21:01:04 (GMT)
commitedb575e758f7ca6cd0390e6ef5444e78971e7cd4 (patch)
treed5b84690fb367ef765b2771c259528240c6c4d61 /Doc
parent7b1559ac2633ec858abdf6fb8b4cfa45b08cbc88 (diff)
downloadcpython-edb575e758f7ca6cd0390e6ef5444e78971e7cd4.zip
cpython-edb575e758f7ca6cd0390e6ef5444e78971e7cd4.tar.gz
cpython-edb575e758f7ca6cd0390e6ef5444e78971e7cd4.tar.bz2
Edits to the PEP 343 section
Diffstat (limited to 'Doc')
-rw-r--r--Doc/whatsnew/whatsnew25.tex127
1 files changed, 62 insertions, 65 deletions
diff --git a/Doc/whatsnew/whatsnew25.tex b/Doc/whatsnew/whatsnew25.tex
index c4f910e..b55e425 100644
--- a/Doc/whatsnew/whatsnew25.tex
+++ b/Doc/whatsnew/whatsnew25.tex
@@ -585,8 +585,7 @@ executed.
In this section, I'll discuss the statement as it will commonly be
used. In the next section, I'll examine the implementation details
-and show how to write objects called ``context managers'' and
-``contexts'' for use with this statement.
+and show how to write objects for use with this statement.
The '\keyword{with}' statement is a new control-flow structure whose
basic structure is:
@@ -596,13 +595,13 @@ with expression [as variable]:
with-block
\end{verbatim}
-The expression is evaluated, and it should result in a type of object
-that's called a context manager. The context manager can return a
+The expression is evaluated, and it should result in an object that
+supports the context management protocol. This object may return a
value that can optionally be bound to the name \var{variable}. (Note
-carefully: \var{variable} is \emph{not} assigned the result of
-\var{expression}.) One method of the context manager is run before
-\var{with-block} is executed, and another method is run after the
-block is done, even if the block raised an exception.
+carefully that \var{variable} is \emph{not} assigned the result of
+\var{expression}.) The object can then run set-up code
+before \var{with-block} is executed and some clean-up code
+is executed after the block is done, even if the block raised an exception.
To enable the statement in Python 2.5, you need
to add the following directive to your module:
@@ -613,7 +612,8 @@ from __future__ import with_statement
The statement will always be enabled in Python 2.6.
-Some standard Python objects can now behave as context managers. File
+Some standard Python objects now support the context management
+protocol and can be used with the '\keyword{with}' statement. File
objects are one example:
\begin{verbatim}
@@ -637,12 +637,11 @@ with lock:
...
\end{verbatim}
-The lock is acquired before the block is executed, and always released once
+The lock is acquired before the block is executed and always released once
the block is complete.
The \module{decimal} module's contexts, which encapsulate the desired
-precision and rounding characteristics for computations, can also be
-used as context managers.
+precision and rounding characteristics for computations, also work.
\begin{verbatim}
import decimal
@@ -660,47 +659,45 @@ with decimal.Context(prec=16):
\subsection{Writing Context Managers\label{context-managers}}
Under the hood, the '\keyword{with}' statement is fairly complicated.
-Most people will only use '\keyword{with}' in company with
-existing objects that are documented to work as context managers, and
-don't need to know these details, so you can skip the following section if
-you like. Authors of new context managers will need to understand the
-details of the underlying implementation.
+Most people will only use '\keyword{with}' in company with existing
+objects and don't need to know these details, so you can skip the
+following section if you like. Authors of new objects will need to
+understand the details of the underlying implementation.
A high-level explanation of the context management protocol is:
\begin{itemize}
\item The expression is evaluated and should result in an object
-that's a context manager, meaning that it has a
-\method{__context__()} method.
+with a \method{__context__()} method.
\item This object's \method{__context__()} method is called, and must
-return a context object.
+return another object that has \method{__enter__()} and
+\method{__exit__()}.
-\item The context's \method{__enter__()} method is called.
-The value returned is assigned to \var{VAR}. If no \code{'as \var{VAR}'}
-clause is present, the value is simply discarded.
+\item This object's \method{__enter__()} method is called. The value
+returned is assigned to \var{VAR}. If no \code{'as \var{VAR}'} clause
+is present, the value is simply discarded.
\item The code in \var{BLOCK} is executed.
-\item If \var{BLOCK} raises an exception, the context object's
+\item If \var{BLOCK} raises an exception, the
\method{__exit__(\var{type}, \var{value}, \var{traceback})} is called
with the exception's information, the same values returned by
-\function{sys.exc_info()}. The method's return value
-controls whether the exception is re-raised: any false value
-re-raises the exception, and \code{True} will result in suppressing it.
-You'll only rarely want to suppress the exception; the
-author of the code containing the '\keyword{with}' statement will
-never realize anything went wrong.
+\function{sys.exc_info()}. The method's return value controls whether
+the exception is re-raised: any false value re-raises the exception,
+and \code{True} will result in suppressing it. You'll only rarely
+want to suppress the exception; the author of the code containing the
+'\keyword{with}' statement will never realize anything went wrong.
\item If \var{BLOCK} didn't raise an exception,
-the context object's \method{__exit__()} is still called,
+the \method{__exit__()} method is still called,
but \var{type}, \var{value}, and \var{traceback} are all \code{None}.
\end{itemize}
Let's think through an example. I won't present detailed code but
-will only sketch the necessary code. The example will be writing a
-context manager for a database that supports transactions.
+will only sketch the methods necessary for a database that supports
+transactions.
(For people unfamiliar with database terminology: a set of changes to
the database are grouped into a transaction. Transactions can be
@@ -721,15 +718,15 @@ with db_connection as cursor:
# ... more operations ...
\end{verbatim}
-The transaction should either be committed if the code in the block
-runs flawlessly, or rolled back if there's an exception.
+The transaction should be committed if the code in the block
+runs flawlessly or rolled back if there's an exception.
First, the \class{DatabaseConnection} needs a \method{__context__()}
-method. Sometimes an object can be its own context manager and can
-simply return \code{self}; the \module{threading} module's lock objects
-can do this. For our database example, though, we need to
-create a new object; I'll call this class \class{DatabaseContext}.
-Our \method{__context__()} must therefore look like this:
+method. Sometimes an object can simply return \code{self}; the
+\module{threading} module's lock objects do this, for example. For
+our database example, though, we need to create a new object; I'll
+call this class \class{DatabaseContext}. Our \method{__context__()}
+method must therefore look like this:
\begin{verbatim}
class DatabaseConnection:
@@ -746,9 +743,9 @@ class DatabaseConnection:
"Rolls back current transaction"
\end{verbatim}
-The context needs the connection object so that the connection
-object's \method{commit()} or \method{rollback()} methods can be
-called:
+Instance of \class{DatabaseContext} need the connection object so that
+the connection object's \method{commit()} or \method{rollback()}
+methods can be called:
\begin{verbatim}
class DatabaseContext:
@@ -756,12 +753,11 @@ class DatabaseContext:
self.connection = connection
\end{verbatim}
-The \method {__enter__()} method is pretty easy, having only
-to start a new transaction. In this example,
-the resulting cursor object would be a useful result,
-so the method will return it. The user can
-then add \code{as cursor} to their '\keyword{with}' statement
-to bind the cursor to a variable name.
+The \method {__enter__()} method is pretty easy, having only to start
+a new transaction. For this application the resulting cursor object
+would be a useful result, so the method will return it. The user can
+then add \code{as cursor} to their '\keyword{with}' statement to bind
+the cursor to a variable name.
\begin{verbatim}
class DatabaseContext:
@@ -798,17 +794,18 @@ class DatabaseContext:
\subsection{The contextlib module\label{module-contextlib}}
The new \module{contextlib} module provides some functions and a
-decorator that are useful for writing context managers.
+decorator that are useful for writing objects for use with the
+'\keyword{with}' statement.
The decorator is called \function{contextmanager}, and lets you write
-a simple context manager as a generator. The generator should yield
-exactly one value. The code up to the \keyword{yield} will be
-executed as the \method{__enter__()} method, and the value yielded
-will be the method's return value that will get bound to the variable
-in the '\keyword{with}' statement's \keyword{as} clause, if any. The
-code after the \keyword{yield} will be executed in the
-\method{__exit__()} method. Any exception raised in the block
-will be raised by the \keyword{yield} statement.
+a simple context manager as a generator function. The generator
+should yield exactly one value. The code up to the \keyword{yield}
+will be executed as the \method{__enter__()} method, and the value
+yielded will be the method's return value that will get bound to the
+variable in the '\keyword{with}' statement's \keyword{as} clause, if
+any. The code after the \keyword{yield} will be executed in the
+\method{__exit__()} method. Any exception raised in the block will be
+raised by the \keyword{yield} statement.
Our database example from the previous section could be written
using this decorator as:
@@ -832,8 +829,9 @@ with db_transaction(db) as cursor:
...
\end{verbatim}
-You can also use this decorator to write the \method{__context__()} method
-for a class without creating a new class for the context:
+You can also use this decorator to write the \method{__context__()}
+method for a class without creating a new class to act as the context
+manager:
\begin{verbatim}
class DatabaseConnection:
@@ -851,8 +849,8 @@ class DatabaseConnection:
\end{verbatim}
-There's a \function{nested(\var{mgr1}, \var{mgr2}, ...)} manager that
-combines a number of context managers so you don't need to write
+There's a \function{nested(\var{mgr1}, \var{mgr2}, ...)} function that
+combines a number of contexts so you don't need to write
nested '\keyword{with}' statements. This example statement does two
things, starting a database transaction and acquiring a thread lock:
@@ -862,7 +860,7 @@ with nested (db_transaction(db), lock) as (cursor, locked):
...
\end{verbatim}
-Finally, the \function{closing(\var{object})} context manager
+Finally, the \function{closing(\var{object})} function
returns \var{object} so that it can be bound to a variable,
and calls \code{\var{object}.close()} at the end of the block.
@@ -880,8 +878,7 @@ with closing(urllib.urlopen('http://www.yahoo.com')) as f:
\seepep{343}{The ``with'' statement}{PEP written by Guido van~Rossum
and Nick Coghlan; implemented by Mike Bland, Guido van~Rossum, and
Neal Norwitz. The PEP shows the code generated for a '\keyword{with}'
-statement, which can be helpful in learning how context managers
-work.}
+statement, which can be helpful in learning how the statement works.}
\seeurl{../lib/module-contextlib.html}{The documentation
for the \module{contextlib} module.}