try..yield..finally problem: a proposed solution.

Andrew Bennetts andrew-pythonlist at puzzling.org
Thu Jun 5 07:03:19 EDT 2003


On Thu, Jun 05, 2003 at 11:47:41AM +0100, Alan Kennedy wrote:
> Dear All,
> 
> After thinking about this some more, I've come to the conclusion that explicitly
> raising "Finality" is the best solution to the try..yield..finally problem, like
> so:
> 
> #--------------------------------
> 
> class Finality(Exception): pass
> 
> try:
>     yield somefunc()
>     raise Finality
> except Finality:
>     print "And finally"
> except:
>     print "An exception occurred"
> 
> #--------------------------------

A much shorter way to write this is:

    try:
        yield somefunc()
        print "And finally"
    except:
        print "An exception occurred"

But a better idiom (and still shorter) is:

    try:
        yield somefunc()
    except:
        print "An exception occurred"
    else:
        print "And finally"

> 3. It achieves the intended purpose clearly and concisely, and doesn't involve
> any changes to the language syntax or semantics.

It also doesn't have the same meaning as a finally block, which is *always*
executed upon leaving its corresponding try block, regardless of the
presence (or absence) of an exception.

A more accurate substitute would be:

    exc = None
    try:
        yield somefunc()
    except:
        exc = sys.exc_info()
    
    print "finally"
    if exc:
        raise exc[0], exc[1], exc[2]

But notice that a yield itself can't raise an exception, so you could in
fact do:

    try:
        x = somefunc()
    finally:
        print "finally"

    yield x

Although this means that the finally will happen before the yield -- but at
least that means it *will* happen, and it's immediately obvious and
unambiguous to the reader when it will happen.  All of the other variants in
this post rely upon the generator being restarted to trigger their final
code, which is rather against the spirit of finally as it is normally used.

-Andrew.






More information about the Python-list mailing list