Reputation: 851
I want to maintain one code-base where I can dynamically enable and disable some set of features for different build version. Of course, I can do this with compiler flags in C/C++ while having several build configurations. But how can I do this with Python? Is there any equivalent technology in Python?
Upvotes: 2
Views: 989
Reputation: 8137
In C, of course, the preprocessor is used to determine which parts of a program are included or excluded. There is a hard and fast delineation between the preprocessor and the main program code.
There is no preprocessor, and thus no such delineation in Python, which might seem strange to a C programmer. But just because there is no such delineation doesn't mean that you cannot reconfigure your application.
Python is extremely dynamic -- one of the nice things about Python is that an application can even be reconfigured "on the fly" by reading configuration files that are either in a specialized format (several are supported in the standard library), or even in Python.
There are advanced ways to reconfigure an application, but the simplest is probably to have a configuration file that is pure Python. For example, you could have a myconfig.py
that has statements like:
use_widgets = True
use_cogs = False
This Python configuration script could even exist where the user is executing the program from; this behavior is easily supported by adding the current directory to the module search path:
import sys
sys.path.insert(0, '.')
import myconfig
As you know, in C, #if
is more efficient than if
because the results are precalculated before execution. Python doesn't have #if
, but unlike C, if
statements can easily exist outside of any function, so you can replace entire sections of code based on your configuration:
if myconfig.use_widgets:
def myfunc(.....):
<definition that uses widgets>
else:
def myfunc(.....):
<non-widget definition>
When the module is imported, Python will compile the whole thing (if it was not already precompiled into a .pyc file), and then execute the body of the module. This execution will bind the first module definition (for the widget-using myfunc
) to the identifier myfunc
in the module's global variables, and immediately discard the non-widget myfunc
(by not executing the else
clause).
This is slightly less efficient at startup than having a single myfunc
, but after startup, there is no run-time penalty -- the second myfunc disappears and is never seen again, and the first myfunc, optimized for the case where you have widgets, is the one that is executed whenever another part of the program calls myfunc
.
Upvotes: 2