Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't Python 2.7 let me implicitly re-raise an exception after yield?

I've noticed some strange behavior in Python 2.7.5 when yielding inside an except: block:

def generator():
    try:
        raise Exception()
    except:
        yield
        raise

list(generator())

This code fails with TypeError: exceptions must be old-style classes or derived from BaseException, not NoneType

Why does Python do that instead of re-raising the exception, as it would have if yield was not before raise?

(Apparently Python 3 has fixed this wart, and the function yields a list of [None] as you would expect.)

(The workaround is to store the exception in a variable: except Exception as e: yield; raise e)

like image 640
joeforker Avatar asked Aug 07 '14 18:08

joeforker


1 Answers

This is just a bug in Python 2.x. According to the bug report, the issue is fixed in Python 3, but due to the complexity of backporting it, the fix never made it to 2.7 before it went into maintenance mode:

This is fixed in Python 3. I don't know if it's worth backporting the changes because it may be hard to avoid also backporting the incompatibilities in the exception model.

Eight months later...

This won't get backported now that 2.7 is in maintenance.

like image 64
dano Avatar answered Oct 31 '22 19:10

dano