How would you do the equivalent of preprocessor directives in Python?

Question:

Is there a way to do the following preprocessor directives in Python?

#if DEBUG

< do some code >

#else

< do some other code >

#endif
Asked By: intrepion

||

Answers:

I suspect you’re gonna hate this answer. The way you do that in Python is

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

Since python is an interpreter, there’s no preprocessing step to be applied, and no particular advantage to having a special syntax.

Answered By: Charlie Martin

You can just use the normal language constructs:

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

You can use the preprocessor in Python. Just run your scripts through the cpp (C-Preprocessor) in your bin directory. However I’ve done this with Lua and the benefits of easy interpretation have outweighed the more complex compilation IMHO.

Answered By: Robert Gould

There’s __debug__, which is a special value that the compiler does preprocess.

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

__debug__ will be replaced with a constant 0 or 1 by the compiler, and the optimizer will remove any if 0: lines before your source is interpreted.

Answered By: habnabit

I wrote a python preprocessor called pypreprocessor that does exactly what you’re describing.

The source and documentation is available on GitHub.

The package can also be downloaded/installed through the PyPI.

Here’s an example to accomplish what you’re describing.

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 is capable of a lot more than just on-the-fly preprocessing. To see more use case examples check out the project on Google Code.

Update: More info on pypreprocessor

The way I accomplish the preprocessing is simple. From the example above, the preprocessor imports a pypreprocessor object that’s created in the pypreprocessor module. When you call parse() on the preprocessor it self-consumes the file that it is imported into and generates a temp copy of itself that comments out all of the preprocessor code (to avoid the preprocessor from calling itself recursively in an infinite loop) and comments out all of the unused portions.

Commenting out the lines is, as opposed to removing them, is necessary to preserve line numbers on error tracebacks if the module throws an exception or crashes. And I’ve even gone as far as to rewrite the error traceback to report reflect the proper file name of the module that crashed.

Then, the generated file containing the postprocessed code is executed on-the-fly.

The upside to using this method over just adding a bunch of if statements inline in the code is, there will be no execution time wasted evaluating useless statements because the commented out portions of the code will be excluded from the compiled .pyc files.

The downside (and my original reason for creating the module) is that you can’t run both python 2x and python 3x in the same file because pythons interpreter runs a full syntax check before executing the code and will reject any version specific code before the preprocessor is allowed to run ::sigh::. My original goal was to be able to develop 2x and 3x code side-by-side in the same file that would create version specific bytecode depending on what it is running on.

Either way, the preprocessor module is still very useful for implementing common c-style preprocessing capabilities. As well as, the preprocessor is capable of outputting the postprocessed code to a file for later use if you want.

Also, if you want to generate a version that has all of the preprocessor directives as well as any of the #ifdefs that are excluded removed it’s as simple as setting a flag in the preprocessor code before calling parse(). This makes removing unwanted code from a version specific source file a one step process (vs crawling through the code and removing if statements manually).

Answered By: Evan Plaice

An alternative method is to use a bash script to comment out portions of code which are only relevant to debugging. Below is an example script which comments out lines that have a ‘#DEBUG’ statement in it. It can also remove these comment markers again.

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
Answered By: slierp
  • Python if cannot eliminate elements from arrays.
  • C precompilers do not handle #! or other lines beginning with # as needed.
  • pypreprocessor seems to be python specific

Use a common m4 instead, like this:

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

Answered By: Torsten Reichert

Use gpp – a general-purpose preprocessor.

Answered By: peter.slizik

I use PIE. https://the-pie-project.codeberg.page/ PIE is the best way to preprocess in Python 3.

Answered By: Peter Smith