Как обрабатывать AssertionError в Python и выяснить, в какую строку или оператор он произошел?
Я хочу обработать AssertionError
как для скрытия ненужных частей трассировки стека от пользователя, так и для печати сообщения о том, почему произошла ошибка и что пользователь должен делать с ней.
Есть ли способ узнать, какая строка или оператор assert
не удалось выполнить в блоке except
?
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:
assert 7 == 7, "7 == 7"
поскольку он повторяет информацию.
Ответы
Ответ 1
Используйте модуль traceback:
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)
Ответ 2
Модуль traceback и sys.exc_info являются излишними для отслеживания источника исключения. Это все в режиме отслеживания по умолчанию. Поэтому вместо вызова exit (1) просто повторно рейз:
try:
assert "birthday cake" == "ice cream cake", "Should've asked for pie"
except AssertionError:
print 'Houston, we have a problem.'
raise
Что дает следующий вывод, который включает в себя выражение о нарушении и номер строки:
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
Аналогично, модуль протоколирования позволяет легко регистрировать трассировку для любого исключения (включая те, которые были пойманы и никогда не воссозданы):
import logging
try:
assert False == True
except AssertionError:
logging.error("Nothing is real but I can't quit...", exc_info=True)