Why doesn't an invalid exception name in an "except" statement cause a NameError immediately?
Question:
Consider this example, with a deliberate typo:
try:
print("Hello!")
raise ValueError("?")
except ValueErro:
print("Error!")
finally:
print("World!")
The handling of the explicitly raised ValueError
results in a NameError
:
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
ValueError: ?
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
NameError: name 'ValueErro' is not defined
However, if a ValueError
is not raised:
try:
print("Hello!")
except ValueErro:
print("Error!")
finally:
print("World!")
then no exception occurs; Hello!
and World!
are simply printed.
Why is there no NameError
caused by the typo ValueErro
(no such name exists)? Shouldn’t this have been detected ahead of time?
Can I use a different syntax to ensure that the problem is caught ahead of time?
Answers:
After a comment from @DYZ, I found the right search terms to get the answer.
https://docs.python.org/3/tutorial/errors.html#handling-exceptions
The try statement works as follows.
-
First, the try clause (the statement(s) between the try and except keywords) is executed.
-
If no exception occurs, the except clause is skipped and execution of the try statement is finished.
Another resource exploring this problem.
https://dbaktiar-on-python.blogspot.com/2009/07/python-lazy-evaluation-on-exception.html
–
My Solution moving forward:
# Explicitly bind the Exception Names in a non-lazy fashion.
errors = (KeyboardInterrupt, ValueErro) # Caught!
try:
print("Hello!")
raise ValueError("?")
except errors:
print("Error!")
finally:
print("World!")
–
tl;dr – The except clauses are entirely skipped if the try clauses executes without exception.
Exceptions can be defined at run time. Example:
myexcept.py contains:
class ValueErro(Exception):
pass
Your program slightly modified:
import_myexcept = False
if import_myexcept:
from myexcept import ValueErro
try:
print("Hello!")
raise ValueError("?")
except ValueErro:
print("Error!")
finally:
print("World!")
This behaves just like your program: NameError: name 'ValueErro' is not defined
.
But change: import_myexcept = True
, and by the time the except ValueErro:
statement is encountered, the ValueErro
exception is defined and no NameError occurs.
Consider this example, with a deliberate typo:
try:
print("Hello!")
raise ValueError("?")
except ValueErro:
print("Error!")
finally:
print("World!")
The handling of the explicitly raised ValueError
results in a NameError
:
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
ValueError: ?
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
NameError: name 'ValueErro' is not defined
However, if a ValueError
is not raised:
try:
print("Hello!")
except ValueErro:
print("Error!")
finally:
print("World!")
then no exception occurs; Hello!
and World!
are simply printed.
Why is there no NameError
caused by the typo ValueErro
(no such name exists)? Shouldn’t this have been detected ahead of time?
Can I use a different syntax to ensure that the problem is caught ahead of time?
After a comment from @DYZ, I found the right search terms to get the answer.
https://docs.python.org/3/tutorial/errors.html#handling-exceptions
The try statement works as follows.
First, the try clause (the statement(s) between the try and except keywords) is executed.
If no exception occurs, the except clause is skipped and execution of the try statement is finished.
Another resource exploring this problem.
https://dbaktiar-on-python.blogspot.com/2009/07/python-lazy-evaluation-on-exception.html
–
My Solution moving forward:
# Explicitly bind the Exception Names in a non-lazy fashion.
errors = (KeyboardInterrupt, ValueErro) # Caught!
try:
print("Hello!")
raise ValueError("?")
except errors:
print("Error!")
finally:
print("World!")
–
tl;dr – The except clauses are entirely skipped if the try clauses executes without exception.
Exceptions can be defined at run time. Example:
myexcept.py contains:
class ValueErro(Exception):
pass
Your program slightly modified:
import_myexcept = False
if import_myexcept:
from myexcept import ValueErro
try:
print("Hello!")
raise ValueError("?")
except ValueErro:
print("Error!")
finally:
print("World!")
This behaves just like your program: NameError: name 'ValueErro' is not defined
.
But change: import_myexcept = True
, and by the time the except ValueErro:
statement is encountered, the ValueErro
exception is defined and no NameError occurs.