How to Handle AssertionError in Python and Identify the Line or Statement Where It Occurred?
I want to handle AssertionError exceptions in Python, both to hide unnecessary parts of the stack trace from the user and to print a clear message explaining why the error occurred and what the user should do about it.
Is there a way to identify the line or statement where the assert failed within the except block?
For example, in the following code:
try:
assert True
assert 7 == 7
assert 1 == 2
# many more statements like this
except AssertionError:
print(‘Houston, we have a problem.’)
print()
print(‘An error occurred on line ??? in statement ???’)
exit(1)
I don’t want to repeat this for every assert statement:
assert 7 == 7, “7 == 7”
How can I find out where the Python AssertionError occurred without needing to add additional information to each assertion?
Hey there! I’ve worked with Python quite a bit, and this is a great question. One simple and effective way to handle this is by using Python’s traceback
module. It lets you inspect the error stack dynamically and figure out where the error happened. Here’s how it works:
import traceback
try:
assert True
assert 7 == 7
assert 1 == 2 # This will raise an AssertionError
except AssertionError:
print('Houston, we have a problem.')
tb = traceback.extract_tb(traceback.format_exc())
error_line = tb[-1]
print(f'An error occurred on line {error_line.lineno} in statement {error_line.line}')
exit(1)
This approach gives you precise details about where the AssertionError
occurred without needing to annotate each assert
. It’s super handy when you want to keep your code clean and informative!
Rima made an excellent point, and I’d like to expand on it with another method that’s also quite powerful. If you’re interested in exploring Python’s inspect
module, you can use it to inspect the call stack and figure out where the AssertionError
was triggered. Here’s an example:
import inspect
try:
assert True
assert 7 == 7
assert 1 == 2 # This will raise an AssertionError
except AssertionError:
print('Houston, we have a problem.')
current_frame = inspect.currentframe()
caller_frame = inspect.getouterframes(current_frame, 2)
line_number = caller_frame[1].lineno
code_context = caller_frame[1].code_context[0].strip()
print(f'An error occurred on line {line_number} in statement: {code_context}')
exit(1)
This gives you both the line number and the actual statement that failed, providing a bit more context than the traceback
approach. It’s great for debugging Python AssertionError in more detail.
Devan and Rima both have shared great ways to identify where an AssertionError
occurs. I’d like to take it a step further with a reusable approach. How about creating a custom assertion function that automatically includes all this information? It makes the code more structured and easier to maintain. Here’s how:
def custom_assert(condition, message="Assertion failed"):
if not condition:
import inspect
current_frame = inspect.currentframe()
caller_frame = inspect.getouterframes(current_frame, 2)
line_number = caller_frame[1].lineno
print(f"Assertion failed at line {line_number}: {message}")
raise AssertionError(message)
try:
custom_assert(True)
custom_assert(7 == 7)
custom_assert(1 == 2) # This will raise an AssertionError
except AssertionError as e:
print(f'Houston, we have a problem. Error: {e}')
exit(1)
With this approach, you can catch and report Python AssertionError with a clear and reusable structure. The custom_assert
function eliminates the need for repetitive patterns and is perfect for handling multiple assertions.