Подтвердить что ты не робот

Как обрабатывать 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"

поскольку он повторяет информацию.

4b9b3361

Ответ 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)