Отключение python assert() без флага -0

Я запускаю python script из другого программного обеспечения (он предоставляет интерфейс python для управления своими структурами данных).

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

Я не могу использовать python -O. Какие у меня есть другие опции, чтобы программно отключить все утверждения в коде python? Переменная __debug__ (которая очищается флагом -O) не может быть назначена: (

Ответ 1

Документы говорят,

Значение встроенной переменной [ __debug__] определяется, когда интерпретатор запускается.

Итак, если вы не можете контролировать, как запущен интерпретатор python, то похоже, что вы не можете отключить assert.

Вот некоторые другие варианты:

  • Самый безопасный способ - вручную удалить все утверждения assert.
  • Если все ваши утверждающие утверждения происходят на линиях сами по себе, то возможно, вы можете удалить их с помощью

    sed -i 's/assert /pass #assert /g' script.py
    

    Обратите внимание, что это приведет к искажению вашего кода, если другой код появится после утверждения. Например, команда sed выше прокомментировала бы return в строке следующим образом:

    assert x; return True
    

    который изменит логику вашей программы.

    Если у вас есть такой код, вероятно, было бы лучше вручную удалить утверждения.

  • Возможно, есть способ удалить их программным путем, проанализировав ваши script с модулем tokenize, но для написания такой программы удаление утверждений может занять больше времени, чем потребуется вручную удалите утверждения, особенно если это одноразовая работа.

  • Если другая часть программного обеспечения принимает файлы .pyc, тогда есть грязный трюк, который, кажется, работает на моей машине, хотя обратите внимание на на Python основной разработчик предупреждает об этом (см. комментарий Éric Araujo 2011-09-17). Предположим, что ваш script называется script.py.

    • Создайте временный script, вызываемый, скажем, temp.py:

      import script
      
    • Запустите python -O temp.py. Это создает script.pyo.
    • Переместите script.py и script.pyc (если он существует) из вашего PYTHONPATH или любой другой каталог, который читает другое программное обеспечение, чтобы найти script.
    • Переименовать script.pyoscript.pyc.

    Теперь, когда другое программное обеспечение пытается импортировать ваш script, он будет только найдите файл pyc, который удаляет утверждения.

    Например, если script.py выглядит так:

    assert False
    print('Got here')
    

    тогда запуск python temp.py теперь будет печатать Got here вместо того, чтобы поднимать AssertionError.

Ответ 2

Возможно, вы сможете сделать это с помощью переменной окружения, как описано в этом другом ответе. Установка PYTHONOPTIMIZE=1 эквивалентна запуску Python с опцией -O. В качестве примера это работает в Blender 2.78, в который встроен Python 3.5:

blender --python-expr 'assert False; print("foo")'

PYTHONOPTIMIZE=1 blender --python-expr 'assert False; print("foo")'

Первая команда печатает трассировку, а вторая просто печатает "foo".

Ответ 3

Как описывает @unutbu, нет официального способа сделать это. Однако простая стратегия заключается в определении флага типа _test где-нибудь (например, как ключевого слова для функции или глобальной переменной в модуле), затем включить это в ваши утверждения следующим образом:

def f(x, _test=True):
    assert not _test or x > 0
    ...

Затем вы можете отключить утверждения в этой функции, если это необходимо.

f(x, _test=False)