[Python-Dev] Compilation of "except FooExc as var" adds useless store
Paul Sokolovsky
pmiscml at gmail.com
Sun Jan 6 06:10:48 EST 2019
More information about the Python-Dev mailing list
Sun Jan 6 06:10:48 EST 2019
- Previous message (by thread): [Python-Dev] Summary of Python tracker Issues
- Next message (by thread): [Python-Dev] Compilation of "except FooExc as var" adds useless store
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Hello, As explained in https://docs.python.org/3/reference/compound_stmts.html#the-try-statement , except E as N: foo is actually compiled as: except E as N: try: foo finally: del N But looking at the generated bytecode, it's worse than that: 16 STORE_NAME 1 (N) 18 POP_TOP 20 SETUP_FINALLY 8 (to 30) 4 22 LOAD_NAME 2 (foo) 24 POP_TOP 26 POP_BLOCK 28 LOAD_CONST 0 (None) >> 30 LOAD_CONST 0 (None) 32 STORE_NAME 1 (N) 34 DELETE_NAME 1 (N) 36 END_FINALLY It's clear that what happens there is that first None is stored to N, just to del it as the next step. Indeed, that's what done in the compile.c: https://github.com/python/cpython/blob/master/Python/compile.c#L2905 Storing None looks superfluous. For example, DELETE_FAST explicitly stores NULL on delete. https://github.com/python/cpython/blob/master/Python/ceval.c#L2249 Likewise, for DELETE_NAME/DELETE_GLOBAL, PyObject_DelItem() is called which translates to: m->mp_ass_subscript(o, key, (PyObject*)NULL); So hopefully any compliant mapping implementation actually clears stored value, not leaving it dangling. The "store None" behavior can be traced down to introduction of the "del except target var" behavior back in 2007: https://github.com/python/cpython/commit/b940e113bf90ff71b0ef57414ea2beea9d2a4bc0#diff-cb296cc5109f5640ff3f6d7198a6abeeR1999 There's no clear explanation why it's done like that, so probably an artifact of the initial implementation. Note that even https://github.com/python/cpython/commit/520b7ae27e39d1c77ea74ccd1b184d7cb43f9dcb which did quite a bunch of refactoring to "except" implementation, and reformatted this code, otherwise left it in place. P.S. I actually wanted to argue that such an implementation is hardly ideal at all. Consider: ---- e = "my precious data" try: 1/0 except Exception as e: pass # Where's my *global* variable? # Worse, my variable can be gone or not, depending on whether exception # triggered or not. print(e) ---- So, perhaps the change should be not removing "e = None" part, but conversely, removing the "del e" part. -- Best regards, Paul mailto:pmiscml at gmail.com
- Previous message (by thread): [Python-Dev] Summary of Python tracker Issues
- Next message (by thread): [Python-Dev] Compilation of "except FooExc as var" adds useless store
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Python-Dev mailing list