(An Unofficial) Python Reference Wiki

"clearly marked experimental"

The with statement

COMMENT: This describes the revised version of the with-statement. See python-dev for discussion.

New in version 2.5.

The with statement is used to wrap the execution of a block with functionality provided by a separate guard object (see context-managers). This allows common try-except-finally usage patterns to be encapsulated for convenient reuse.

To enable in 2.5:

from __future__ import with_statement

Syntax:

with expression [as target] :
    suite

or:

with expression [as ( target list ) ] :
    suite

The expression is evaluated once, and should yield a context guard, which is used to control execution of the suite. The guard can provide execution-specific data, which is assigned to the target (or target list).

Note that if a target list is used instead of a single target, the list must be parenthesized.

Here's a more detailed description:

  1. The context expression is evaluated, to obtain a context guard.
  2. The guard object's __enter__ method is invoked to obtain the context entry value.
  3. The context entry value is assigned to the target or target list, if present.
  4. The suite is executed.
  5. No matter what happens in the suite, the guard object's __exit__ method is invoked. If an exception caused the suite to be exited, its type, value, and traceback are passed as arguments to __exit__. Otherwise, three None arguments are supplied.

If the suite was exited due to an exception, and the return value from the __exit__ method is false, the exception is reraised. If the return value is true, the exception is suppressed, and execution continues with the statement following the with statement.

If the suite was exited for any reason other than an exception (e.g., by falling off the end of the suite, or via return, break, or continue), the return value from __exit__ is ignored, and execution proceeds at the normal location for the kind of exit that was taken.

Note: The with statement guarantees that if the __enter__ method returns without an error, then __exit__ will always be called. Thus, if an error occurs during the assignment to the target list, it will be treated the same as an error occurring within the suite would be. See step 5 above.

Note: In Python 2.5, the with statement is only allowed when the with_statement feature has been enabled. It will always be enabled in Python 2.6. This __future__ import statement can be used to enable the feature (see future):

from __future__ import with_statement

See Also: PEP 0343, The "with" statement The specification, background, and examples for the Python with statement.

Comments

(effbot: fixed markup glitch)

Users trying this out should be aware that the latest 2.5 release, 2.5a2, implements a slightly different protocol whereby the guard object is obtained by calling the __context__() method on the expression in the with-statement. However, in most cases __context__() returns self, so the effect is the same (the decimal.Context class is the one exception). In Python 2.5a3 the __context__() method will be gone, and the above description will apply.

Also note that the syntax only allows a single target. IOW this is valid::

with foo as bar:
    pass

But this is not::

with foo as bar, bletch:
    pass

You can write this instead::

with foo as (bar, bletch):
    pass

The reason is to leave a possibility open in the future to extend the syntax to allow multiple context guards; this could be spelled in one of the following ways::

with G1, G2 as x1, x2:
    pass

or::

with G1 as x1, G2 as x2:
    pass