[BangPypers] How to create Debug and Release code in Python
Jeff Rush
jeff at taupro.com
Tue Jun 16 08:27:35 CEST 2009
Vishal wrote:
>
> *Is there a way to create a conditionally compilable Python script
> ?* Some facility that would prevent from code getting compiled into
> ".pyc"....something like the old #ifdef #endif preprocessor
> directives....is there a Python preprocessory available :)
I've given this more thought. In the April 2009 issue of Python
Magazine is a wonderful article by Paul McGuire on writing Domain
Specific Languages. It shows how to intercept the import of specific
types of files to preprocess the source before compiling it into
bytecode. I played with those ideas to see what could be done for your
case.
So say you had a module marked up with special commenting like:
--- cut here --- abc.pyp
def main():
print "Hello" #? DEBUG
print "There" #? DEBUG2
print "World"
--- cut here --- abc.pyp
Then in your main module you could do the following:
--- cut here --- demo.py
import cond_importer # can put in site.py for global application
import abc
abc.main()
--- cut here --- demo.py
Now you run the program normally and get:
$ python2.5 demo.py
Hello
There
World
or you can filter out lines using:
$ EXCLUDES=DEBUG python2.5 demo.py
There
World
or even:
$ EXCLUDES=DEBUG:DEBUG2 python2.5 demo.py
World
The magic to make this happen is just:
--- cut here --- cond_import.py
from __future__ import with_statement # for Python < 2.6
import os
import imputil
import re
patt = re.compile(r".*#\? (?P<tag>[_a-zA-Z][_a-zA-Z0-9]*)$")
try: # construct a set of tags to exclude in .py source
pyexcludes = frozenset(os.environ['EXCLUDES'].split(':'))
except Exception:
pyexcludes = frozenset()
def preprocess_source(filepath, fileinfo, filename):
src = []
with file(filepath, 'r') as f:
for line in f:
m = patt.match(line)
if m is None or m.group('tag') not in pyexcludes:
src.append(line)
src = '\n'.join(src)
codeobj = compile(src, filepath, 'exec')
# create return tuple:
# import flag (0=module, 1=package)
# code object
# dictionary of variable definitions
return 0, codeobj, {}
importer = imputil.ImportManager()
importer.add_suffix('.pyp', preprocess_source)
importer.install()
--- cut here --- cond_import.py
I arbitrarily chose a file extension of .pyp for files to preprocess but
you could use anything. And the tags to exclude could instead be tags
to include. For handling packages (dirs) instead of modules you'd have
to add a test for file or directory and change the code a bit.
Anyway it raises some interesting possibilities of preprocessing.
Python is just so cool.
-Jeff
More information about the BangPypers
mailing list