Python assert - улучшенный самоанализ неудачи?

Это довольно бесполезная ошибка утверждения; он не сообщает значения задействованного выражения (предположим, что используемые константы на самом деле являются именами переменных):

$ python -c "assert 6-(3*2)"
[...]
AssertionError

Есть ли лучшеassert реализация в Python, что более модно? Он не должен вводить дополнительные накладные расходы на выполнение (кроме случаев, когда assert не выполняется) .. и должен отключаться, если-O флаг используется.

редактировать: Я знаю об утвержденииВторой аргумент в виде строки. Я неЯ не хочу писать один ... как это закодировано в выражении, которое утверждается. СУХОЙ (Дон 'Повторите себя).

Ответы на вопрос(7)

что вы действительно хотите сделать, это установить точку останова отладчика непосредственно передassert и проверяйте от своего любимого отладчика столько, сколько хотите.

которое будет отображаться в случае сбоя подтверждения:

$ python -c "assert 6-(3*2), '6-(3*2)'"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AssertionError: 6-(3*2)
</module></string>

Единственный способ обеспечить это автоматически - это включить утверждение в вызов процедуры, а затем проверить стек, чтобы получить исходный код для этой строки. К сожалению, дополнительный вызов привнесет в тест служебные данные и не будет отключен с помощью.-O

 Sridhar Ratnakumar20 авг. 2009 г., 23:19
Точно. Это отключает этоинтроспекция» на -О, это ключ к вопросу.
 Sridhar Ratnakumar20 авг. 2009 г., 23:20
.. НО это не накладные расходы, если эта функция вызывается только во время ошибок подтверждения (не вызовов подтверждения).

sys.excepthook (который вызывается для любого необработанного исключения), что немного более необычно, чем стандартное. Он проанализирует строку, в которой произошло исключение, и напечатает все переменные, на которые ссылается эта строка (он не напечатает все локальные переменные, потому что это может быть слишком много шума - также, возможно, важный переменный является глобальным или около того).

Я назвал это py_better_exchook (идеальное имя), и этоВот.

Пример файла:

a = 6

def test():
    unrelated_var = 43
    b,c = 2, 3
    assert a - b*c

import better_exchook
better_exchook.install()

test()

Выход:

$ python test_error_reporting.py 
EXCEPTION
Traceback (most recent call last):
  File "test_error_reporting.py", line 12, in <module>
    line: test()
    locals:
      test = <local> <function test="" at="" 0x7fd91b1a05f0="">
  File "test_error_reporting.py", line 7, in test
    line: assert a - b*c
    locals:
      a = <global> 6
      b = <local> 2
      c = <local> 3
AssertionError
</local></local></global></function></local></module>

Есть несколько других альтернатив:

(Представлено здесь)https://github.com/albertz/py_better_exchook/https://github.com/patrys/great-justiceНос делает что-то подобное для ошибок утверждения,посмотреть здесь.У IPython есть что-то похожее (этот). Сделай это: .from IPython.core import ultratb; sys.excepthook = ultratb.VerboseTB()Ка-Пинг Йи "cgitb.py», который является частью Python,посмотреть здесь,код здесь.

Как@ Марк Рушаков сказал nose может оценить ошибочные утверждения. Работает по стандартуassert тоже.'

# test_error_reporting.py
def test():
    a,b,c = 6, 2, 3
    assert a - b*c

nosetests Помогите:

$ nosetests --help|grep -B2 assert
  -d, --detailed-errors, --failure-detail
                        Add detail to error output by attempting to evaluate
                        failed asserts [NOSE_DETAILED_ERRORS]

Пример:

$ nosetests -d
F
======================================================================
FAIL: test_error_reporting.test
----------------------------------------------------------------------
Traceback (most recent call last):
  File "..snip../site-packages/nose/case.py", line 183, in runTest
    self.test(*self.arg)
  File "..snip../test_error_reporting.py", line 3, in test
    assert a - b*c
AssertionError:
    6,2,3 = 6, 2, 3
>>  assert 6 - 2*3


----------------------------------------------------------------------
Ran 1 test in 0.089s

FAILED (failures=1)
 Sridhar Ratnakumar21 авг. 2009 г., 01:23
Тот'звучит интересно; Жаль, что Python нене иметьmacro особенность.
 Sridhar Ratnakumar20 авг. 2009 г., 23:54
Вопрос касается использования assert в коде приложения (который напрямую вызывается пользователем, например, ./foo.py .. или нажатием на 'foo.pyw» в Windows Explorer), а не тестовый код .. за что я на самом деле доволен py.test 'Подтвердите вывод.
 jfs29 окт. 2013 г., 00:15
@SridharRatnakumar: есть (сейчас)macropy
 congusbongus10 авг. 2015 г., 08:31
Чтобы интроспекция работала, вы также должны опуститьmsg параметр.
 jfs21 авг. 2009 г., 00:04
@srid: в этом случае напишите:__debug__ and your_fancy_assert(expression) - без накладных расходов-O».

sys.excepthook -- увидетьдокументы, Ваша функция, если второй аргументAssertionError, может самоанализ твоему сердцус содержанием; в частности, через третий аргумент, traceback, он может получить фрейм и точное место, в котором произошел сбой подтверждения, получение сбойного исключения через источник или байт-код, значение всех соответствующих переменных и т. д. Модульосмотреть помогает.

Делать это в полной общности - это довольно трудоемко, но в зависимости от того, какие ограничения выготовы принять в том, как вы пишетеasserts это может быть значительно облегчено (например, ограничение их только локальными или глобальными переменными делает интроспекцию легче, чем если бы могли быть задействованы нелокальные переменные замыкания и т. д.).

 Sridhar Ratnakumar21 авг. 2009 г., 21:40
Хорошо. Теперь есть библиотека Python для этого .. или я должен написать свою собственную? :-) (Я, вероятно, выиграл 'т. как для меня это легкая задача)
 Alex Martelli22 авг. 2009 г., 20:36
К сожалению я неt не знаю о существующих библиотеках Python, делающих все это, за исключением библиотек, ориентированных на тестирование (которые, возможно, придется адаптировать для целей использования их в рабочем коде).

Вы можете прикрепить сообщение к:assert

assert 6-(3*2), "always fails"

Сообщение также может быть построено динамически:

assert x != 0, "x is not equal to zero (%d)" % x

Увидетьassert заявление в документации по Python для получения дополнительной информации.

 Greg Hewgill21 авг. 2009 г., 00:08
Я понимаю, что вы имеете ввиду. Я неЯ не верю, что у Python есть способ сделать это.
 Sridhar Ratnakumar20 авг. 2009 г., 23:17
Конечно, я знал это. Я неЯ не хочу писать так, как это закодировано в выражении, которое утверждается. DRY.

Пакет тестирования носа применяет самоанализ к утверждениям.

Тем не менее, AFAICT, вы должны позвонитьих утверждает, чтобы получить самоанализ:

import nose
def test1():
    nose.tools.assert_equal(6, 5+2)

результаты в

C:\temp\py>C:\Python26\Scripts\nosetests.exe -d test.py
F
======================================================================
FAIL: test.test1
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Python26\lib\site-packages\nose-0.11.1-py2.6.egg\nose\case.py", line
183, in runTest
    self.test(*self.arg)
  File "C:\temp\py\test.py", line 3, in test1
    nose.tools.assert_equal(6, 5+2)
AssertionError: 6 != 7
>>  raise self.failureException, \
          (None or '%r != %r' % (6, 7))

Обратите внимание на ошибку AssertionError. Когда моя линия была простоassert 6 == 5+2, Я бы получил:

C:\temp\py>C:\Python26\Scripts\nosetests.exe -d test.py
F
======================================================================
FAIL: test.test1
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Python26\lib\site-packages\nose-0.11.1-py2.6.egg\nose\case.py", line
183, in runTest
    self.test(*self.arg)
  File "C:\temp\py\test.py", line 2, in test1
    assert 6 == 5 + 2
AssertionError:
>>  assert 6 == 5 + 2

Также я'Я не уверен, что их утверждения пропущены с-O, но это будет очень быстрая проверка.

 Sridhar Ratnakumar20 авг. 2009 г., 23:21
Достаточно хорошо для тестовых случаев, но для производственного кода .. есть издержки вызова функции (даже с опцией -O)
 jfs20 авг. 2009 г., 23:50
Обычные утверждения тоже работают. Увидетьstackoverflow.com/questions/1308607/...

Ваш ответ на вопрос