Как бы вы сделали эквивалент директив препроцессора в Python?

StackOverflow https://stackoverflow.com/questions/482014

Вопрос

Есть ли способ выполнить следующие директивы препроцессора в Python?

#if DEBUG

< do some code >

#else

< do some other code >

#endif
Это было полезно?

Решение

Есть __debug__, которое представляет собой специальное значение, которое компилятор предварительно обрабатывает.

if __debug__:
  print "If this prints, you're not running python -O."
else:
  print "If this prints, you are running python -O!"

__debug__ будет заменено компилятором на константу 0 или 1, а оптимизатор удалит все if 0: строк перед интерпретацией вашего источника.

Другие советы

Я написал препроцессор Python под названием pypreprocessor, который делает именно то, что вы описываете.

Исходный код и документация доступны на GitHub..

Пакет также можно загрузить/установить через PyPI..

Вот пример выполнения того, что вы описываете.

from pypreprocessor import pypreprocessor

pypreprocessor.parse()

#define debug

#ifdef debug
print('The source is in debug mode')
#else
print('The source is not in debug mode')
#endif

pypreprocessor способен на гораздо большее, чем просто предварительную обработку на лету.Чтобы увидеть больше примеров использования, посетите проект в Google Code.

Обновлять:Дополнительная информация о pypreprocessor

Способ выполнения предварительной обработки прост.В приведенном выше примере препроцессор импортирует объект pypreprocessor, созданный в модуле pypreprocessor.Когда вы вызываете parse() в препроцессоре, он самостоятельно потребляет файл, в который он импортирован, и генерирует свою временную копию, которая комментирует весь код препроцессора (чтобы препроцессор не вызывал себя рекурсивно в бесконечном цикле) и закомментирует все неиспользуемые части.

Комментирование строк, а не их удаление, необходимо для сохранения номеров строк при отслеживании ошибок, если модуль выдает исключение или происходит сбой.И я даже дошел до того, что переписал отслеживание ошибок, чтобы в отчете отражалось правильное имя файла модуля, который вышел из строя.

Затем сгенерированный файл, содержащий код постобработки, выполняется «на лету».

Преимущество использования этого метода по сравнению с простым добавлением в код нескольких операторов if заключается в том, что не будет тратиться время выполнения на оценку бесполезных операторов, поскольку закомментированные части кода будут исключены из скомпилированных файлов .pyc.

Обратной стороной (и моей первоначальной причиной создания модуля) является то, что вы не можете запускать Python 2x и Python 3x в одном и том же файле, поскольку интерпретатор Python выполняет полную проверку синтаксиса перед выполнением кода и отклоняет любой код конкретной версии перед выполнением. препроцессору разрешено работать ::sigh::.Моя первоначальная цель заключалась в том, чтобы иметь возможность одновременно разрабатывать код 2x и 3x в одном файле, который создавал бы байт-код для конкретной версии в зависимости от того, на чем он выполняется.

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

Кроме того, если вы хотите сгенерировать версию, в которой удалены все директивы препроцессора, а также любые исключенные #ifdef, это так же просто, как установить флаг в коде препроцессора перед вызовом parse().Это делает удаление нежелательного кода из исходного файла конкретной версии одноэтапным процессом (по сравнению с сканированием кода и удалением операторов if вручную).

Я подозреваю, что тебе не понравится этот ответ.То, как вы это делаете в Python,

# code here
if DEBUG:
   #debugging code goes here
else:
   # other code here.

Поскольку Python является интерпретатором, нет необходимости применять этап предварительной обработки и нет особого преимущества в наличии специального синтаксиса.

Вы можете использовать препроцессор в Python.Просто запустите свои сценарии через cpp (C-препроцессор) в каталоге bin.Однако я сделал это с Lua, и преимущества простой интерпретации, ИМХО, перевесили более сложную компиляцию.

Вы можете просто использовать обычные языковые конструкции:

DEBUG = True
if DEBUG:
  # Define a function, a class or do some crazy stuff
  def f():
    return 23
else:
  def f():
    return 42

Альтернативный метод — использовать сценарий bash для закомментирования частей кода, которые имеют отношение только к отладке.Ниже приведен пример сценария, который комментирует строки, содержащие оператор #DEBUG.Он также может снова удалить эти маркеры комментариев.

if [ "$1" == "off" ]; then
  sed -e '/^#/! {/#DEBUG/ s/^/#/}' -i *.py
  echo "Debug mode to $1"
elif [ "$1" == "on" ]; then
  sed -e '/#DEBUG/ s/^#//' -i *.py
  echo "Debug mode to $1"
else
  echo "usage: $0 on | off"
fi
  • Python, если не может удалять элементы из массивов.
  • Прекомпиляторы C не обрабатывают #!или другие строки, начинающиеся с #, по мере необходимости.
  • pypreprocessor кажется специфичным для Python

Вместо этого используйте обычный m4, например:

ifelse(DEBUG,True,dnl`
  < do some code >
dnl,dnl`
  < do some other code >dnl
')

ifelse(
  M4_CPU,x86_64,`
    < do some code specific for M4_CPU >
',M4_CPU,arm,`
    < do some code specific for M4_CPU >
',M4_CPU,ppc64le,`
    < do some code specific for M4_CPU >
')

ifelse(
  M4_OS,windows,`
    < do some code specific for M4_OS >
  ',M4_OS,linux,`
    < do some code specific for M4_OS >
  ',M4_OS,android,`
    < do some code specific for M4_OS >
')

m4 -D DEBUG=True -D M4_OS=android -D M4_CPU=arm test.py.m4 > test.py

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top