如何在 Python 中处理 AssertionError 并找出它发生在哪一行或哪一条语句上?

我希望处理 AssertionError,这样既可以向用户隐藏堆栈跟踪的不必要部分,又可以打印一条消息,说明错误发生的原因以及用户应该如何处理。

有没有办法找出 except块中哪一行或哪一条语句的 assert失败了?

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)

我不想在每个断言语句中都加上这个:

assert 7 == 7, "7 == 7"

因为它会重复信息。

198456 次浏览

Use the traceback module:

import sys
import traceback


try:
assert True
assert 7 == 7
assert 1 == 2
# many more statements like this
except AssertionError:
_, _, tb = sys.exc_info()
traceback.print_tb(tb) # Fixed format
tb_info = traceback.extract_tb(tb)
filename, line, func, text = tb_info[-1]


print('An error occurred on line {} in statement {}'.format(line, text))
exit(1)

The traceback module and sys.exc_info are overkill for tracking down the source of an exception. That's all in the default traceback. So instead of calling exit(1) just re-raise:

try:
assert "birthday cake" == "ice cream cake", "Should've asked for pie"
except AssertionError:
print 'Houston, we have a problem.'
raise

Which gives the following output that includes the offending statement and line number:

Houston, we have a problem.
Traceback (most recent call last):
File "/tmp/poop.py", line 2, in <module>
assert "birthday cake" == "ice cream cake", "Should've asked for pie"
AssertionError: Should've asked for pie

Similarly the logging module makes it easy to log a traceback for any exception (including those which are caught and never re-raised):

import logging


try:
assert False == True
except AssertionError:
logging.error("Nothing is real but I can't quit...", exc_info=True)