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 -- https://mail.python.org/mailman/listinfo/python-list