variable scope in try ... EXCEPT block.

Chris Angelico rosuav at
Thu Jul 12 09:03:01 EDT 2018

On Thu, Jul 12, 2018 at 10:31 PM, Ed Kellett <e+python-list at> wrote:
> On 2018-07-12 10:59, Steven D'Aprano wrote:
>> 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 [...]
> "necessary" is debatable. When we have reference counting, general
> garbage collection, *and* nasty hacks like this, one could be forgiven
> for thinking Python has chosen the worst of all memory-management worlds.

I don't understand you. Are you saying that there are other memory
management systems that are perfect, without any tradeoffs? Because
the problem here is a reference cycle thus:

>>> def f():
...  try: 1/0
...  except Exception as e: print(e is e.__traceback__.tb_frame.f_locals["e"])
>>> f()

Dealing with reference cycles is generally done *periodically* rather
than immediately (CPython disposes of unreferenced objects immediately
upon last deref). You can avoid having a dedicated cycle detection
pass by using a mark-and-sweep GC, but that just means that *all*
garbage is dealt with periodically rather than immediately. I can
imagine having some sort of flag on every object that's involved in a
cycle, and then doing a mini-GC every time any of those objects gets
any dereferencing, but that would be ridiculously expensive. There are
ALWAYS tradeoffs. How is Python's arrangement "the worst"?

Personally, I think this would be better with an *actual* subscope.
But apparently that's a ridiculously insane suggestion with no chance
whatsoever of being accepted. Kinda like assignment expressions.


More information about the Python-list mailing list