python - 在多处理模块中为每个进程重新加载 Python 模块

标签 python python-multiprocessing python-module

有没有办法在使用 Python 的多处理模块创建的进程中加载​​每个进程的模块副本?我试过这个:

def my_fn(process_args):
    import my_module
    my_func()

...但是 my_module 中的子导入会被一次性加载和缓存。特别是,其中一个子导入会读取一个配置文件,该文件的值是根据第一个进程的环境设置的。如果我尝试这个:

def my_fn(process_args):
    try:
        my_module = reload(my_module)
    except NameError:
        import my_module

...my_module 的子导入不会重新加载。

最佳答案

您可以尝试通过检查要重新加载的模块并重新加载它使用的任何模块来实现深度重新加载功能。这并不是万无一失的,例如无法应对以下情况:

class MyClass:
    module = import_module('amodule')

但很可能足以满足您的目的。

mymod.py

# Example submodule to re-import
print('import module mymod')

# demonstrate we can even import test as a module and it works
import sys
from test import deep_reload_module

value = 2

def a_function():
    pass

class XYZ:
    pass

class NewClass(object):
    pass

测试.py

import importlib
import sys
import mymod


def deep_reload_module(name):

    mod = sys.modules.get(name)
    if not mod:
        importlib.import_module(name)
        return

    def get_mods_to_reload_recursively(name, modules_to_reload=None):
        modules_to_reload = modules_to_reload or set()
        mod = sys.modules[name]
        modules_to_reload.add(name)

        # loop through the attributes in this module and remember any
        # submodules we should also reload
        for attr in dir(mod):
            prop = getattr(mod, attr)
            if isinstance(prop, type(mymod)):
                modname = attr
            elif hasattr(prop, '__module__'):
                modname = prop.__module__
                if not modname:
                    continue
            else:
                # this thing is not a module nor does it come from another
                # module, so nothing to reimport.
                continue

            if modname in sys.builtin_module_names:
                # probably best not to reimport built-ins...
                continue

            if modname in modules_to_reload:
                # this is already marked for reimporting, so avoid infinite
                # recursion
                continue

            # get_mods_to_reload... will update modules_to_reload so no need to
            # catch the return value
            get_mods_to_reload_recursively(modname, modules_to_reload)

        return modules_to_reload

    mods_to_reload = get_mods_to_reload_recursively(name)
    for mtr in mods_to_reload:
        # best to delete everything before reloading so that you are
        # sure things get re-hooked up properly to the new modules.
        print('del sys.modules[%s]' % (mtr,))
        del sys.modules[mtr]

    importlib.import_module(name)


if __name__ == '__main__':
    orig_mymod_id = id(sys.modules['mymod'])
    deep_reload_module('mymod')
    assert orig_mymod_id != id(sys.modules['mymod'])

那么您只需调用 deep_reload_module('module')每当新进程启动时,或者在每个多处理作业开始时更容易。

注意:这在很大程度上依赖于您想要重新导入的模块外部的代码,之前没有从该模块导入任何内容,因为如果有,那么该代码将继续使用旧的模块或中断。

例如如果您有执行此操作的代码:

from module_to_reimport import a_function

但没有保留module_to_reimport任何明确的地方,然后 a_function当模块重新导入后调用它时,它很可能会失败,因为它只维护对 globals() 的弱引用。定义于 module_to_reimport通过从 sys.modules 中删除模块,这些都会被消灭。 .

关于python - 在多处理模块中为每个进程重新加载 Python 模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42411448/

相关文章:

python - 尝试根据系列四分位数中的相应位置将 pandas df 系列的 float 转换为四个分类值之一

python - 在函数 Python 之间传递列表

python - 清理多处理中的子进程

python - 为什么多处理模块可以pickle调用匿名函数的函数?

python - 是否可以在没有循环导入的情况下在模块中导入 flask 配置值?

python - 在python3中实现枚举类型的比较运算符

Python 循环一直错误返回,我该如何修改?

python - 在Python中的多个进程之间共享存储对象的字典

python - python中的导入规则是什么

python - 尽管尝试了多种建议,但无法在 Python 中导入本地模块