Update this PEP to reflect the new design: exceptions are swallowed only
when __exit__ returns a true value.
This commit is contained in:
parent
03a9d2dab8
commit
f6659b5348
29
pep-0343.txt
29
pep-0343.txt
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue