Как вы реализуете "#ifdef " в python?
Программирование C
раньше у меня были разделы кода, используемые только для отладки (команды ведения журнала и тому подобное). Эти операторы могут быть полностью отключены для производства с помощью #ifdef
директивы препроцессора, такие как этот:
#ifdef MACRO
controlled text
#endif /* MACRO */
каков наилучший способ сделать что-то подобное в python
?
7 ответов
если вы просто хотите отключить методы ведения журнала, используйте logging
модуль. Если уровень журнала установлен на исключение, скажем, операторов отладки, то logging.debug
будет очень близко к no-op (он просто проверяет уровень журнала и возвращает без интерполяции строки журнала).
если вы хотите фактически удалить куски кода во время компиляции байт-кода, обусловленные определенной переменной, ваш единственный вариант-довольно загадочный __debug__
глобальная переменная. Эта переменная имеет значение True
если -O
флаг передается Python (или PYTHONOPTIMIZE
имеет значение что-то непустое в среде).
если __debug__
используется if
заявление if
оператор фактически компилируется только в True
филиала. Эта конкретная оптимизация настолько близка к макросу препроцессора, насколько это вообще возможно для Python.
обратите внимание, что в отличие от макросов, ваш код должен быть синтаксически правильным в обоих ветвей if
.
показать как!--4--> работает, рассмотрим эти две функции:
def f():
if __debug__: return 3
else: return 4
def g():
if True: return 3
else: return 4
теперь проверьте их с dis
:
>>> dis.dis(f)
2 0 LOAD_CONST 1 (3)
3 RETURN_VALUE
>>> dis.dis(g)
2 0 LOAD_GLOBAL 0 (True)
3 JUMP_IF_FALSE 5 (to 11)
6 POP_TOP
7 LOAD_CONST 1 (3)
10 RETURN_VALUE
>> 11 POP_TOP
3 12 LOAD_CONST 2 (4)
15 RETURN_VALUE
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
Как видите, только f
это "оптимизацией".
важно понимать, что в Python def
и class
два обычных исполняемых операторов...
import os
if os.name == "posix":
def foo(x):
return x * x
else:
def foo(x):
return x + 42
...
Итак, чтобы сделать то, что вы делаете с препроцессором на C и c++, вы можете использовать обычный язык Python.
язык Python принципиально отличается от C и C++ на этом этапе, потому что нет понятия "время компиляции" , и только две фазы - "время синтаксического анализа" (когда исходный код считывается) и "время выполнения", когда анализируемый код (обычно в основном состоит из операторов определения, но это действительно произвольный код Python) выполняется.
я использую термин "время разбора", даже если технически, когда исходный код читается в преобразовании, является полной компиляцией в байт-код, потому что семантика компиляции C и C++ отличается, и, например, определение функции происходит на этом этапе (в то время как вместо этого это происходит во время выполнения в Python).
даже эквивалент #include
C и C++ (что в Python import
) - это обычный оператор, который выполняется во время выполнения, а не во время компиляции (разбора), поэтому его можно поместить внутри обычного python if
. Довольно распространенным является, например, наличие import
внутри try
блок, который предоставит альтернативные определения для некоторых функций, если в системе нет определенной дополнительной библиотеки Python.
наконец, обратите внимание, что в Python вы даже можете создавать новые функции и классы во время выполнения с нуля использование exec
, не обязательно иметь их в исходном коде. Вы также можете собирать эти объекты напрямую с помощью кода, потому что классы и функции действительно являются обычными объектами (обычно это делается только для классов).
есть некоторые инструменты, которые вместо этого пытаются рассмотреть def
и class
определений и import
операторы как "статические", например, для статического анализа кода Python для генерации предупреждений о подозрительных фрагментах или для создания автономный развертываемый пакет, который не зависит от наличия определенной установки Python в системе для запуска программы. Однако все они должны учитывать, что Python более динамичен, чем C или C++ в этой области, и они также позволяют добавлять исключения для случаев сбоя автоматического анализа.
насколько я знаю, вы должны использовать if
заявления. Нет препроцессора, поэтому нет аналога директивам препроцессора.
Edit: на самом деле, похоже, что верхний ответ на этот вопрос будет более освещающим: как бы вы сделали эквивалент директив препроцессора в Python?
предположительно существует специальная переменная __debug__
который, при использовании с if
оператор, будет оцениваться один раз, а затем не оценивается снова во время выполнения.
вот пример, который я использую для различения Python 2 & 3 для моих программ Python Tk:
import sys if sys.version_info[0] == 3: from tkinter import * from tkinter import ttk else: from Tkinter import * import ttk """ rest of your code """
надеюсь, что это полезная иллюстрация.
нет прямого эквивалента, о котором я знаю, поэтому вы можете уменьшить масштаб и пересмотреть проблемы, которые вы использовали для решения с помощью препроцессора.
Если это просто диагностическое ведение журнала вы после того, как есть всеобъемлющий модуль ведения журнала, который должен охватывать все, что вы хотели и многое другое.
http://docs.python.org/library/logging.html
для чего еще вы используете препроцессор? Тестовые конфигурации? Есть конфиг модуль для этого.
http://docs.python.org/library/configparser.html
что-нибудь еще?
если вы используете #ifdef
для проверки переменных, которые могут быть определены в области выше текущего файла, можно использовать исключения. Например, у меня есть скрипты, которые я хочу запускать по-другому изнутри ipython
против за пределами ipython
(например, показать участки против сохранения участков). Поэтому я добавляю
ipy = False
try:
ipy = __IPYTHON__
except NameError:
pass
это оставляет меня с переменным ipy
, который говорит мне, является ли или нет __IPYTHON__
был объявлен в области выше моего текущего скрипта. Это самая близкая параллель, которую я знаю для Ан #ifdef
функция в Python.
на ipython
, это отличное решение. Аналогичные конструкции можно использовать и в других контекстах, в которых вызывающий скрипт задает значения переменных, а внутренние скрипты проверяются соответствующим образом. Имеет ли это смысл, конечно, будет зависеть от вашего конкретного случая использования.
Я сам не пробовал, но как насчет https://code.google.com/p/pypreprocessor/