variable scope in try ... EXCEPT block.
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Thu Jul 12 05:59:52 EDT 2018
On Thu, 12 Jul 2018 01:37:24 -0700, aleiphoenix wrote:
> My question is, does except ... as ... create a new scope from outer
> block, causing 'err' be hidden from outer scope? Is this intentional?
No, it is not a new scope, and yes, it is intentional. It's a nasty hack,
but a *necessary* nasty hack: when the except block exits, the "err"
local variable (or whatever it happens to be called) is implicitly
deleted.
You can work around this by explicitly assigning to another local
variable:
try:
...
except Exception as e:
err = e # only "e" will be deleted when we exit the block
This is necessary in Python 3 (but not Python 2) because exception
objects form a reference cycle with something (the traceback?) which is a
big, heavyweight object. Allowing random exception objects to stay alive
for long periods was consuming unacceptable amounts of memory, so it was
decided to hit this problem with a hammer and fix it in the simplest,
although least elegant, way: just delete the exception when leaving the
except block.
You can see the disassembled byte-code here. Here's the output from
Python 3.5:
py> dis.dis("try: pass\nexcept Exception as err: pass")
1 0 SETUP_EXCEPT 4 (to 7)
3 POP_BLOCK
4 JUMP_FORWARD 37 (to 44)
2 >> 7 DUP_TOP
8 LOAD_NAME 0 (Exception)
11 COMPARE_OP 10 (exception match)
14 POP_JUMP_IF_FALSE 43
17 POP_TOP
18 STORE_NAME 1 (err)
21 POP_TOP
22 SETUP_FINALLY 5 (to 30)
25 POP_BLOCK
26 POP_EXCEPT
27 LOAD_CONST 0 (None)
>> 30 LOAD_CONST 0 (None)
33 STORE_NAME 1 (err)
36 DELETE_NAME 1 (err)
39 END_FINALLY
40 JUMP_FORWARD 1 (to 44)
>> 43 END_FINALLY
>> 44 LOAD_CONST 0 (None)
47 RETURN_VALUE
--
Steven D'Aprano
"Ever since I learned about confirmation bias, I've been seeing
it everywhere." -- Jon Ronson
More information about the Python-list
mailing list