1

I am confused about the exception handling in python3. Say that I want to catch an exception and store it for later use; why doesn't the following code work? (it raises a NameError: name 'e' is not defined)

try:
    [][0]
except IndexError as e:
    pass
e

Why is e treated as a local variable within the try block? As a way around, I realized that I could "reassign" it; namely, the following code works:

try:
    [][0]
except IndexError as e:
    z = e
z

But then, why does the following still not work?

try:
    [][0]
except IndexError as e:
    e = e
e

The code above still raises a NameError: name 'e' is not defined; but shouldn't e = e behave exactly the same as z = e?

Then again, I did find a solution to use the exception as I want, but I would appreciate your help in understanding why the other two attempts fail. Thank you in advance.

2 Answers 2

2

It doesn't work like z because e is already defined here except IndexError as e:. You make it equal to itself and then, after catch block it disappears because it's not in the scope anymore.

When you assigned z it's a new variable, it won't be cleared after that block.

Sign up to request clarification or add additional context in comments.

Comments

1

A less ambiguous way of handling errors how you are intending would be as such:

error = None
try:
    [][0]
except IndexError as e:
    error = e
if error:
    pass # handle error here

or

errors = []
try:
    [][0]
except IndexError as e:
    errors.append(e)
if errors:
    pass # handle error(s) here

I have always found python's local scoping a bit confusing and concerning that things that happen within a scope are accessible after their scope.

The reason z is accessible outside of the scope and e is not, is because e is properly cleaned up after it goes out of scope. Where as z seems to be left behind. But my examples show a more explicit way to show what is actually happening (no ambiguity). In your third example the reason e still doesn't exist is because e is still slated to be cleaned up after the scope even though the value has changed the original reference has not.

2 Comments

Thank you for the detailed explanation. What puzzles me is that this "local" behavior does not occur in python2 with except IndexError, e:. Any reason why python3 handles it differently?
I'd believe the clean up is actually an improvement so it is new to python3 because it is working towards cleaning up the scope properly. Python2 allows this but this could be ambiguous, Python3 makes it harder for it to be ambiguous as to what is going to happen.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.