Re: try: execpt:/ try: finally: behavior

Guido.van.Rossum@cwi.nl
Tue, 28 Jun 1994 19:47:46 +0200

> The stack in the call to bar on try statement at point of raising my_exec2
> will look something like:
>
> @finally - contains raising my_exec <- current stack position
> entering bar
> @my_exec - inner one
> @my_exec2
> @my_exec - outer one
> entering foo
> #bottom - top level
>
> and we raise the my_exec2 exception in the 'try' part in bar.
> Scan back and find the @my_exec2 marker in the stack. Now
> either intervening exception markers are allowed to stay active or
> they are not; in this case the inner @my_exec is at issue.
> Now we need to do any finally clauses (top down) on the stack
> that lie between the top (current position) and the called exception
> marker, @my_exec2. The @finally clause raises the my_exec exception.

Ah, there's your lack of understanding of how Python exceptions work.
There is no @my_exec2 marker on the stack. There is only a marker
specifying that a try...except clause is present. Its except clause
headers (the names of the exceptions) are evaluated only when an
exception reaches the marker -- otherwise, try...except would be much
more expensive (Python is a dynamic language, so the exception
identities would have to be evaluated each time a try clause was
entered -- currently all that's needed is to push a blank marker).

In your model, first the except clause corresponding to the exception
is selected, then the finally clauses are executed. However this is
not the way I want it, nor can it be done this way. Selecting the
except clause is done in the context of the block containing the
except clauses; the finally clauses are executed before the except
clause is selected, "on the way out" so to speak. Changing the order
would mean that control flow would have to go UP the stack (from the
except clause back to the finally clause). This is impossible in
Python's execution model: once you have left a block you cannot
re-enter it. (The reason is that there's a C stack frame
corresponding to the Python stack frame -- this is essential for
Python's extensibility, otherwise C could could not call back on
Python code. Once the C frame has been left it is destroyed.)
Placing markers on the stack to identify the various exceptions being
caught would complicate the stack data structure and increase
execution overhead. It would also be incompatible with the exception
handling as it is currently exposed to C extensions.

Concluding, finally clauses are not supposed to raise exceptions -- if
they do, it's your problem.

> I think that is a better semantics of exceptions than the current
> implementation, however, it should be documented which ever is decided
> upon.

The reference manual clearly explains the current exception model. I
don't think additional documentation is needed.

Please let's put this subject to rest.

--Guido van Rossum, CWI, Amsterdam <Guido.van.Rossum@cwi.nl>
URL: <http://www.cwi.nl/cwi/people/Guido.van.Rossum.html>