Injecting variables into an import namespace

前端 未结 2 722
被撕碎了的回忆
被撕碎了的回忆 2020-12-11 11:37

To illustrate what I am trying to do, let\'s say I have a module testmod that lives in ./testmod.py. The entire contents of this module is

相关标签:
2条回答
  • 2020-12-11 11:57

    You could screw with Python's builtins to inject your own fake built-in test variable:

    import builtins    # __builtin__, no s, in Python 2
    
    builtins.test = 5  # or whatever other placeholder value
    
    import testmod
    
    del builtins.test  # clean up after ourselves
    
    0 讨论(0)
  • 2020-12-11 12:04

    I came up with a solution based on this answer and the importlib docs. Basically, I have access to the module object before it is loaded by using the correct sequence of calls to importlib:

    from importlib.util import spec_from_file_location, module_from_spec
    from os.path import splitext, basename
    
    def loadConfig(fileName):
        test = 'This is a test'
        name = splitext(basename(fileName))[0]
        spec = spec_from_file_location(name, fileName)
        config = module_from_spec(spec)
        config.test = test
        spec.loader.exec_module(config)
        return config
    
    testmod = loadConfig('./testmod.py')
    

    This is a bit better than modifying builtins, which may have unintended consequences in other parts of the program, and may also restrict the names I can pass in to the module.

    I decided to put all the configuration items into a single field accessible at load time, which I named config. This allows me to do the following in testmod:

    if 'test' in config:
        x = config['test']
    

    The loader now looks like this:

    from importlib.util import spec_from_file_location, module_from_spec
    from os.path import splitext, basename
    
    def loadConfig(fileName, **kwargs):
        name = splitext(basename(fileName))[0]
        spec = spec_from_file_location(name, fileName)
        config = module_from_spec(spec)
        config.config = kwargs
        spec.loader.exec_module(config)
        return config
    
    testmod = loadConfig('./testmod.py', test='This is a test')
    
    0 讨论(0)
提交回复
热议问题