有没有办法在使用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的子导入不会重新加载。
答案 0 :(得分:1)
您可以尝试通过检查模块来重新加载和重新加载它使用的任何模块来实现深度重载功能。这不是万无一失的,例如不会应对如下:
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
test.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')
,或者在每个多处理作业开始时更轻松。
NB:这很大程度上依赖于你想要重新导入的模块之外的代码以前没有从该模块导入任何东西,因为如果它有,那么该代码将继续使用旧的模块或休息。
E.g。如果你有代码执行此操作:
from module_to_reimport import a_function
但是没有明确地保留module_to_reimport
,那么a_function
在重新导入模块后调用它时可能会失败,因为它只维护对globals()
中定义的module_to_reimport
的弱引用。 sys.modules
并且通过从with timeout(seconds=3)
sleep(4)
删除模块来消除这些内容。
答案 1 :(得分:0)
将函数放入my_module
,例如:
def my_realod():
try:
my_sub_module = reload(my_sub_module)
except NameError:
import my_sub_module
像这样呼叫my_reload
:
def my_fn(process_args):
try:
my_module = reload(my_module)
my_module.my_reload()
except NameError:
import my_module