Сохранение утверждения несмотря на флаг -O (оптимизировать) - PullRequest
2 голосов
/ 29 марта 2012

Я ставлю много проверок состояния программы, ошибка которых может указывать на ошибку в коде.В таких случаях я хотел бы использовать assert condition просто потому, что он читается лучше, чем if not condition: raise MyException.

. Использование assert вместо raise имеет две проблемы.

  1. assert не позволяет указать исключение, которое должно быть вызвано, поэтому перехват его позже становится трудным (перехват AssertionError может перехватить слишком много).

  2. assertотключается, когда флаг -O передается интерпретатору.

В моей среде любая ошибка в коде требует, чтобы я отбрасывал любые результаты, пока ошибка не будет идентифицирована и исправлена.Поэтому нет смысла ловить исключения, вызванные вышеуказанными проверками.Таким образом, проблема № 1 не имеет значения в моей ситуации.

Проблема № 2 серьезна.Я хочу, чтобы мои проверки оставались в рабочем коде, так как правильность гораздо важнее, чем производительность в моей среде.Мало кто сегодня использует -O флаг;но однажды я или кто-то другой может предпочесть использовать его (например, для подавления кода, стоящего за if __debug__, или потому, что -O может фактически оптимизировать код в будущем).Поскольку все мои операторы assert должны оставаться активными в производственном коде, мне нужно заменить все операторы assert чем-то другим.Есть ли способ заставить assert остаться несмотря на флаг -O?

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

1 Ответ

3 голосов
/ 29 марта 2012

Только не используйте утверждения, если они не то, что вам нужно.Вместо этого будьте явными, что вы выбросите это исключение, если какое-то условие будет нарушено.Утверждение assert всегда содержит сторону «я могу или не могу запускаться вообще».Он менее хакерский, менее удивительный, с меньшей вероятностью сломается в будущем и не требует, чтобы пользователи не добавляли -O.

Если вы просто хотите сохранить набор текста, вы можете сделать это.Создайте функцию, подобную этой (настоятельно рекомендуется использовать более конкретное имя), и используйте ее вместо assert:

def require(cond, msg):
    if not cond:
        raise MyException(msg)
...