Making a copy of an entire namespace?

后端 未结 3 1098
Happy的楠姐
Happy的楠姐 2021-02-01 10:44

I\'d like to make a copy of an entire namespace while replacing some functions with dynamically constructed versions.

In other words, starting with namespace (impo

3条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-02-01 10:51

    Instead of trying to make a copy of the contents of a module and patch everything in it to use the correct globals, you could trick Python into importing everything you want to copy a second time. This will give you a newly initialized copy of all modules, so it won't copy any global state the modules might have (not sure whether you would need that).

    import importlib
    import sys
    
    def new_module_instances(module_names):
        old_modules = {}
        for name in module_names:
            old_modules[name] = sys.modules.pop(name)
        new_modules = {}
        for name in module_names:
            new_modules[name] = importlib.import_module(name)
        sys.modules.update(old_modules)
        return new_modules
    

    Note that we first delete all modules we want to replace from sys.modules, so they all get import a second time, and the dependencies between these modules are set up correctly automatically. At the end of the function, we restore the original state of sys.modules, so everything else continues to see the original versions of these modules.

    Here's an example:

    >>> import logging.handlers
    >>> new_modules = new_module_instances(['logging', 'logging.handlers'])
    >>> logging_clone = new_modules['logging']
    >>> logging
    
    >>> logging_clone
    
    >>> logging is logging_clone
    False
    >>> logging is logging.handlers.logging
    True
    >>> logging_clone is logging_clone.handlers.logging
    True
    

    The last three expressions show that the two versions of logging are different modules, and both versions of the handlers module use the correct version of the logging module.

提交回复
热议问题