2017-02-23 4 views
10

Есть ли способ загрузить копии процессов для процессов в процессах, созданных с использованием многопроцессорного модуля Python? Я пробовал это:Перезагрузка модуля 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

Похожие темы: https://bytes.com/topic/python/answers/22688-multiple-instances-modules –

+0

Спасибо Xin, но ответы на эту тему предполагают, что вы написали данный модуль. Тот, который рассматривается здесь, - это одно плохо написанное - с состоянием в модулях вместо классов. – er0

ответ

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 
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.

Смежные вопросы