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

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

#if DEBUG

< do some code >

#else

< do some other code >

#endif

9 ответов

Решение

Там в __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, который делает именно то, что вы описываете.

Источник и документация доступны в Google Code.

Пакет также можно скачать / установить через 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() для препроцессора, он самостоятельно потребляет файл, в который он импортирован, и генерирует временную копию самого себя, которая закомментирует весь код препроцессора (чтобы избежать препроцессора от рекурсивного вызова себя в бесконечном цикле) и комментирует все неиспользованные части.

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

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

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

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

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

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

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

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

Поскольку python является интерпретатором, нет никакого шага предварительной обработки, который нужно применять, и нет особого преимущества, связанного с наличием специального синтаксиса.

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

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

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

Используйте gpp — препроцессор общего назначения.

  • 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

Я использую ПИРОГ . PIE — лучший способ предварительной обработки в Python 3. PIE позволяет выполнять любую предварительную обработку в Python.

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

      #define debug

#ifdef debug
print('The source is in debug mode')
#else
print('The source is not in debug mode')
#endif
Другие вопросы по тегам