【问题标题】:Deep Reload Modules from only One Package仅从一个包中深度重新加载模块
【发布时间】:2017-08-09 18:33:11
【问题描述】:

如何在不从任何其他外部包导入模块的情况下深度重新加载包?

例如,用于重新加载以下内容:

# example_pkg.py
import logging  # do not reload this stdlib package
import example_pkg.ex_mod  # reload this module

IPython 的 deepreload 模块无法为导入指定白名单,并在重新加载期间使用模块级变量,这使得它对于线程环境不可靠。

before 提出了类似的问题,但它侧重于发现依赖关系(就像评论中的 mentioned 一样),而不仅仅是在单个包中。

【问题讨论】:

    标签: python python-import


    【解决方案1】:

    使用 sysimportlib 模块,可以编写一个函数来从 Python 的导入缓存中删除包及其模块。这允许包在重新导入时重新加载其子模块。

    import sys
    import importlib
    from types import ModuleType
    
    def deep_reload(m: ModuleType):
        name = m.__name__  # get the name that is used in sys.modules
        name_ext = name + '.'  # support finding sub modules or packages
        del m
        
        def compare(loaded: str):
            return (loaded == name) or loaded.startswith(name_ext)
        
        all_mods = tuple(sys.modules)  # prevent changing iterable while iterating over it
        sub_mods = filter(compare, all_mods)
        for pkg in sub_mods:
            del sys.modules[pkg]  # remove sub modules and packages from import cache
        
        return importlib.import_module(name)
    

    可以使用Lock 扩展此代码以使其也成为线程安全的:

    from threading import Lock
    
    sys_mod_lock = Lock()  # all accesses to sys.modules must be programmed to acquire this lock first
    # this means do not use any builtin import mechanism such as the 'import' statement once the following function is being used
    # instead use importlib's import_module function while sys_mod_lock is acquired
    
    def tsafe_reload(m: ModuleType):
        with sys_mod_lock:
            return deep_reload(m)
    

    注意:这些函数带有来自标准库reload 的警告之一。程序中其他地方指向旧包的任何引用都将被保留,并且不会被自动替换。为此,您可以查看globalsub,它可以将解释器中对某个对象的所有引用替换为不同的对象(通常用于调试目的)。

    【讨论】:

    • 您的代码中有两个拼写错误:sub_pkgs 应该是 sub_mods,并且应该删除一个额外的冒号。但它有效。
    • @CarlosPinzón 已编辑。感谢您的更正。
    猜你喜欢
    • 2012-12-10
    • 1970-01-01
    • 2014-03-12
    • 2016-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-19
    相关资源
    最近更新 更多