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