Комментарии 19
Похоже вы так и не разобрались для чего нужен assert
.
Он нужен в первую очередь для "sanity checks": проверять то, что в продакшн системе валидировать не нужно (так как не имеет смысла или слишком дорого). Каждый упавший assert должен означать ошибку в вашем коде. Если вы допускаете, что в системе при каких-то обстоятельствах выражение в assert будет ложным, то в этом месте вам assert не подоходит - там должна быть полноценная валидация.
PS: В целом очень странно начинать статью с заведомо неправильного определения этого ключевого слова. 90% проблем и вопросов отпадает, если сразу написать правильное определение.
С вашим пониманием назначения assert совершенно согласен. Но вот разработчики pydantic, например, так не считают. Там assert может использоваться для валидации входящих данных. Мне показалось это очень интересным, поэтому постарался обратить на это внимание в статье.
эмм... а зачем вы его использовали в продакшене, если в доке буквально написано: "assert предназначен для отладки"
https://docs.python.org/3/reference/simple_stmts.html#the-assert-statement
Это стоит рассказать ещё и разработчикам pytest, потому что debugging ≠ testing. Но они упорно используют assert в тестировании.
не вижу противоречий в использовании assert при тестировании:
1. кому и для чего может понадобиться запускать тесты в отладочном режиме?
2. тестирование это тоже своего рода отладка
кому и для чего может понадобиться запускать тесты в отладочном режиме?
В имели в виду с интерпретатором в режиме оптимизации?
именно это я и имел в виду, абсолютно верно
Какой смысл тестировать отладочную сборку, когда в прод будет исполняться совсем другой код?
Сам pytest, как ни странно, работает и с включённой оптимизацией в питоне. Но с ограничениями: assert поддерживается только в модулях с тестами и плагинах. Это реализовано через кастомный загрузчик тестов, который фактически переписывает код. В том числе он заменяет assert на raise AssertionError.
Если вы один из тех редких индивидуумов, которые гоняют тесты в режиме оптимизации и вам не терпится об этом кому-то рассказать, то не пишите мне больше, это максимально не интересно.
Не переживате так, берите пример со специалистов. На эту тему можно вполне конструктивно общаться https://discuss.python.org/t/does-anyone-use-o-or-oo-or-pythonoptimize-1-in-their-deployments/37671/8.
Концептуально, ассерты это больше документация, нежели код.
Да, она выполняется в режиме отладки для удобства, но это вторично. Их отключают в сборках для продакшен, чтобы не снижать перфоманс.
Общее правило: assert не должны ни каким образом влиять на логику выполнения программы (как встроенная документация или логирование, например). Поведение программы с включенными ассертами должно быть точно таким же как и с выключенными.
Если нужна проверка, которая должна менять поток исполнения программы: валидация входных и выходных данных, проверка ошибок времени исполнения, и т.п - то нужно использовать другие выразительные средства языка (такие как if, raise, да хоть монады %). Но не assert.
В питоне подложили свинью: по умолчанию __debug__ включен и AssertionError наследуется от Exception. В результате они бросаются и перехватываются наряду с другими исключениями времени исполнения. Это дало соблазн горячим головам применять их в качестве API для управления логикой программы: в валидаторах, юнит тестах и т.п. Дичь, но от pytest уже ни куда не деться.
В общем, если использовать assert по делу, то ни чего плохого в них нет. Но в питоне, порой, здесь приходится бороться с когнитивным диссонансом.
Собственно, все вопросы к авторам Pydantic. У них же должна быть веская причина игнорировать официальную документацию.
Все остальные указанные случаи - только указывают на смысл assert - отладка кода.
Аналогично в С, где assert натурально удаляется из кода при оптимизированной сборке. И все впитывают с самого начала знание не ожидать сайдэффектов при вызове ассерта. Ну потому зачем оставлять в коде проверки, которые не должны существовать, но были полезны при отладке.
А зачем кому-то запускать тесты с pytest с оптимизациями? Это же скорее всего юнит-тесты, упал-отладил. А для всего прочего со сложного логикой pytest.fail().
Суть assert, как уже подмечено выше, именно в проверке только внутренних инвариантов программы и тестах. И то, что в pydantic его затащили для проверок данных - это косяк проектирования и не верное использование инструмента.
Использование и применение очень похожи на то, как это реализовано в Java: использование-assert
Я бы вообще от Python отказался.
Это косяк авторов pydantic, а не дизайн. По идее им можно отправить баг репорт.
Ни в C/C++, ни в Python, ни в Java assert не предназначены для проверки чего-то в продакшене, это официально указано в документации и опция релизного режима их тихо и незаметно отключает.
Есть дискуссия трехлетней давности https://github.com/pydantic/pydantic/discussions/4575. В v2 они сами не кидают AssertionError из валидаторов, но по-прежнему перехватывают, превращая в ошибки валидации.
Почему мы отказались от выражения «assert» в Python