Update this PEP to reflect the new design: exceptions are swallowed only

when __exit__ returns a true value.
This commit is contained in:
Guido van Rossum 2006-03-09 17:39:53 +00:00
parent 03a9d2dab8
commit f6659b5348
1 changed files with 17 additions and 12 deletions

View File

@ -236,7 +236,9 @@ Specification: The 'with' Statement
except:
# The exceptional case is handled here
exc = False
exit(*sys.exc_info())
if not exit(*sys.exc_info()):
raise
# The exception is swallowed if exit() returns true
finally:
# The normal and non-local-goto cases are handled here
if exc:
@ -277,17 +279,21 @@ Specification: The 'with' Statement
BLOCK, ctx.__exit__() is called with three arguments representing
the exception type, value, and traceback.
IMPORTANT: if ctx.__exit__() is passed exception information, it
*must* re-raise the exception, unless it wants the exception to be
ignored. That is, if ctx.__exit__() returns normally, execution
IMPORTANT: if ctx.__exit__() returns a "true" value, the exception
is "swallowed". That is, if it returns "true", execution
continues at the next statement after the with-statement, even if
an exception happened inside the with-statement. However, if the
with-statement was left via a non-local goto (break, continue or
return), this non-local return is resumed when ctx.__exit__()
returns normally. The motivation for this detail is to make a
try/except block in a context manager created from a decorated
generator behave exactly as if the body of the generator were
expanded in-line at the place of the with-statement.
returns regardless of the return value. The motivation for this
detail is to make it possible for ctx.__exit__() to swallow
exceptions, without making it too easy (since the default return
value, None, is false and this causes the exception to be
re-raised). The main use case for swallowing exceptions is to
make it possible to write the @contextmanager decorator so thatn
that a try/except block in a decorated generator behaves exactly
as if the body of the generator were expanded in-line at the place
of the with-statement.
The motivation for passing the exception details to __exit__(), as
opposed to the argument-less __exit__() from PEP 310, was given by
@ -351,10 +357,9 @@ Generator Decorator
else:
try:
self.gen.throw(type, value, traceback)
except (type, StopIteration):
return
else:
raise RuntimeError("generator caught exception")
return True
except StopIteration:
return True
def contextmanager(func):
def helper(*args, **kwds):