Search code examples
pythonpreprocessor

How do you implement "#ifdef" in python?


Programming in C I used to have code sections only used for debugging purposes (logging commands and the like). Those statements could be completely disabled for production by using #ifdef pre-processor directives, like this:

 #ifdef MACRO

 controlled text

 #endif /* MACRO */

What is the best way to do something similar in python?


Solution

  • If you just want to disable logging methods, use the logging module. If the log level is set to exclude, say, debug statements, then logging.debug will be very close to a no-op (it just checks the log level and returns without interpolating the log string).

    If you want to actually remove chunks of code at bytecode compile time conditional on a particular variable, your only option is the rather enigmatic __debug__ global variable. This variable is set to True unless the -O flag is passed to Python (or PYTHONOPTIMIZE is set to something nonempty in the environment).

    If __debug__ is used in an if statement, the if statement is actually compiled into only the True branch. This particular optimization is as close to a preprocessor macro as Python ever gets.

    Note that, unlike macros, your code must still be syntactically correct in both branches of the if.


    To show how __debug__ works, consider these two functions:

    def f():
        if __debug__: return 3
        else: return 4
    
    def g():
        if True: return 3
        else: return 4
    

    Now check them out with 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        
    

    As you can see, only f is "optimized".