[Python-Dev] Compilation of "except FooExc as var" adds useless store
As explained in
except E as N:
is actually compiled as:
except E as N:
But looking at the generated bytecode, it's worse than that:
16 STORE_NAME 1 (N)
20 SETUP_FINALLY 8 (to 30)
4 22 LOAD_NAME 2 (foo)
28 LOAD_CONST 0 (None)
>> 30 LOAD_CONST 0 (None)
32 STORE_NAME 1 (N)
34 DELETE_NAME 1 (N)
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
Storing None looks superfluous. For example, DELETE_FAST explicitly
stores NULL on delete.
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:
There's no clear explanation why it's done like that, so probably an
artifact of the initial implementation. Note that even
which did quite a bunch of refactoring to "except" implementation, and
reformatted this code, otherwise left it in place.
I actually wanted to argue that such an implementation is hardly ideal
at all. Consider:
e = "my precious data"
except Exception as e:
# Where's my *global* variable?
# Worse, my variable can be gone or not, depending on whether exception
# triggered or not.
So, perhaps the change should be not removing "e = None" part, but
conversely, removing the "del e" part.
Paul mailto:pmiscml at gmail.com