Есть ли способ выполнить следующие директивы препроцессора в Python?
#if DEBUG
< do some code >
#else
< do some other code >
#endif
Есть ли способ выполнить следующие директивы препроцессора в 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:
строки до того, как ваш исходный код будет интерпретирован.
-O
. :-) Я не думал, что это возможно, пока не прочитал это!
- person jonny; 26.11.2015
assert
использует __debug__
, что делает утверждения разработки еще более осязаемыми: docs.python.org/2/reference/simple_stmts.html#assert
- person jonny; 27.11.2015
Я написал препроцессор 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 в одном и том же файле, потому что интерпретатор pythons выполняет полную проверку синтаксиса перед выполнением кода и отклонит любой код конкретной версии перед выполнением. препроцессору разрешен запуск ::sigh::. Моя первоначальная цель состояла в том, чтобы иметь возможность разрабатывать 2x и 3x код бок о бок в одном файле, который создавал бы байт-код для конкретной версии в зависимости от того, на чем он работает.
В любом случае, модуль препроцессора по-прежнему очень полезен для реализации общих возможностей предварительной обработки в стиле C. Кроме того, препроцессор может выводить постобработанный код в файл для последующего использования, если вы хотите.
Кроме того, если вы хотите сгенерировать версию, в которой удалены все директивы препроцессора, а также любые исключенные #ifdef, это так же просто, как установить флаг в коде препроцессора перед вызовом parse(). Это делает удаление нежелательного кода из исходного файла конкретной версии одношаговым процессом (по сравнению с обходом кода и удалением операторов if вручную).
pip install
не работает (кто-то уже задокументировал эту проблему в репозитории).
- person David S.; 29.03.2020
Я подозреваю, что ты возненавидишь этот ответ. То, как вы это делаете в Python,
# code here
if DEBUG:
#debugging code goes here
else:
# other code here.
Поскольку python является интерпретатором, нет необходимости применять этап предварительной обработки и нет особого преимущества в наличии специального синтаксиса.
Вы можете использовать препроцессор в Python. Просто запустите свои скрипты через cpp (C-Preprocessor) в вашем каталоге 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
Вместо этого используйте обычный 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