Pre-processing Imports in Python
Inspired by David Beazley’s talk on various hacks that can be made to Python’s import system, I whipped up the following script for running a preprocessor over a file at import-time. In most cases, I would say this is far from a good idea, but it might be useful for creating small domain-specific languages, or defining new literals, or something like that.
import sys
import re
class ImportPreprocessor:
def __init__(self, loader, preprocess):
self._loader = loader
self._preprocess = preprocess
def find_spec(self, name, path, target=None):
spec = self._loader.find_spec(name, path, target)
spec.loader = ImportPreprocessor(spec.loader, self._preprocess)
return spec
def exec_module(self, mod):
source = self.loader.get_source(mod.__name__)
source = self._preprocess(source)
code = compile(source, mod.__file__, 'exec')
exec(code, mod.__dict__)
return mod
def percent_to_float(source):
pattern = r'(\d+)%'
source = re.sub(pattern, r'(\1/100)', source)
return source
sys.meta_path[3] = ImportPreprocessor(sys.meta_path[3], percent_to_float)
import test
"""
# contents of test.py
x = 40 * 25%
"""
print(test.x) # 10.0