2

I stumbled on an interesting scenario following this question. Consider the following simple example:

try:
    1/0
    error = "error"
except Exception as error:
    print(error)

print(error)

The output is:

division by zero
Traceback (most recent call last):
  File "main.py", line 7, in <module>
    print(error)
NameError: name 'error' is not defined

What happens is of course the first assignment to error is skipped because of the exception, and the except is executed. It prints the exception and - to my understanding - assigns, in a way, the exception object to error. But then, surprisingly, the following print complains that error is not defined.

I tried to understand the scoping rule for exceptions but all I could find in the Exceptions docs was this:

The variable is bound to an exception instance

Which doesn't really explain what is the scope or life-span of this exception instance.

The most similar construct I can think of is a with statement, which doesn't behave the same way:

with open("test.txt") as file:
    pass

file.read()

This code will output a maybe expected output of:

Traceback (most recent call last):
  File "main.py", line 4, in <module>
    file.read()
ValueError: I/O operation on closed file.

But still it is not a NameError which means that file is well-defined.

So can anyone explain what are the scoping rules for exception handling and what is happening here?

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61

1 Answers1

3

This is documented under, The try statement

When an exception has been assigned using as target, it is cleared at the end of the except clause. This is as if

except E as N:
    foo

was translated to

except E as N:
    try:
        foo
    finally:
        del N

This means the exception must be assigned to a different name to be able to refer to it after the except clause

Abdul Niyas P M
  • 18,035
  • 2
  • 25
  • 46