74

有没有办法在 Python 中执行以下预处理器指令?

#if DEBUG

< do some code >

#else

< do some other code >

#endif
4

8 回答 8

122

__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:在解释您的源代码之前删除任何行。

于 2009-01-27T03:25:06.353 回答
40

我编写了一个名为 pypreprocessor 的 python 预处理器,它完全符合您的描述。

源代码和文档可在 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 语句)。

于 2010-06-07T06:46:27.720 回答
26

我怀疑你会讨厌这个答案。你在 Python 中这样做的方式是

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

由于 python 是一个解释器,因此不需要应用预处理步骤,并且具有特殊语法也没有特别的优势。

于 2009-01-27T01:14:24.790 回答
11

您可以在 Python 中使用预处理器。只需通过 bin 目录中的 cpp(C 预处理器)运行脚本。然而,我已经用 Lua 做到了这一点,并且易于解释的好处超过了更复杂的编译恕我直言。

于 2009-01-27T01:16:14.070 回答
5

您可以只使用正常的语言结构:

DEBUG = True
if DEBUG:
  # Define a function, a class or do some crazy stuff
  def f():
    return 23
else:
  def f():
    return 42
于 2009-01-27T01:14:28.690 回答
2

另一种方法是使用 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
于 2015-07-07T06:47:17.927 回答
1
  • Python if 不能从数组中消除元素。
  • 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

于 2019-01-22T16:30:47.807 回答
0

使用gpp - 一个通用的预处理器。

于 2022-02-22T13:50:40.887 回答