classification
Title: except-as in Py3 eats variables
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.1, Python 3.2
process
Status: closed Resolution: not a bug
Dependencies: Superseder: SyntaxError when free variable name is also an exception target
View: 4617
Assigned To: Nosy List: ezio.melotti, flox, scoder
Priority: normal Keywords:

Created on 2010-03-13 07:32 by scoder, last changed 2010-03-13 08:48 by flox. This issue is now closed.

Messages (5)
msg100993 - (view) Author: Stefan Behnel (scoder) * (Python committer) Date: 2010-03-13 07:32
Python 3.2a0 (py3k:78205M, Feb 16 2010, 17:32:08)
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> e = None
[50279 refs]
>>> e
[50279 refs]
>>> try: raise ValueError
... except ValueError as e: pass
...
[50277 refs]
>>> e
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'e' is not defined
[50277 refs]


Same for 3.1.1. Note how the refcount is going down after the try-except.
msg100994 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2010-03-13 07:39
This is a not a bug and it's documented: http://docs.python.org/py3k/reference/compound_stmts.html#the-try-statement

The solution is to assign the value to another variable:
>>> try: raise ValueError
... except ValueError as e: exc = e
...
>>> exc
ValueError()
>>> e
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'e' is not defined
msg100995 - (view) Author: Stefan Behnel (scoder) * (Python committer) Date: 2010-03-13 07:45
I knew that the variable was supposed to go out of scope when leaving the except block, but I wasn't aware that this was supposed to be done using (the equivalent of) a 'del'. Were the side-effects of deleting variables defined outside of the try-except considered negligible at the time? I can't see a warning about that in the docs.
msg100996 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2010-03-13 08:00
In this case I don't see much difference between deleting a variable or assigning it to something else.

This code works on both Python 2 and 3:
>>> e = 'test'
>>> try: pass                    # no errors raised here
... except Exception as e: pass  # this is not executed
...
>>> e
'test'

If you do this instead:
>>> e = 'test'
>>> try: raise ValueError        # raise the error
... except Exception as e: pass  # this is executed
...

On both 2.x and 3.x 'e' doesn't refer to 'test' anymore in the moment that the exception is captured by the except, so what happens next to the "new e" is not related to what the "old e" was.
msg100997 - (view) Author: Florent Xicluna (flox) * (Python committer) Date: 2010-03-13 08:48
See also #4617, with some patch.
History
Date User Action Args
2011-05-13 07:31:31mark.dickinsonlinkissue12064 superseder
2010-03-13 08:48:44floxsetsuperseder: SyntaxError when free variable name is also an exception target

messages: + msg100997
nosy: + flox
2010-03-13 08:00:36ezio.melottisetmessages: + msg100996
2010-03-13 07:45:08scodersetmessages: + msg100995
2010-03-13 07:39:28ezio.melottisetstatus: open -> closed
priority: normal


nosy: + ezio.melotti
messages: + msg100994
resolution: not a bug
stage: resolved
2010-03-13 07:32:37scodercreate