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?

Asked By: erhlee.bird

||

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.

Answered By: erhlee.bird

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.

Answered By: codingatty
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.