python importlib не удается загрузить модули

#python #python-importlib

Вопрос:

Раньше у меня было приложение на python, которое динамически загружало расширения, подобные этому:

 # ./pymodules.py
import importlib, sys

class ExternalModule:
    def __init__(self, mod_name):
        sys.dont_write_bytecode = True
        try:
            module = importlib.import_module(mod_name)
            importlib.reload(module)
            loadedclass = getattr(module, 'Extension')
            self.instance = loadedclass()
        except Exception as e:
            print('Warning:', e)

    def Run(self):
        if hasattr(self, 'instance'):
            return self.instance.method()

if __name__ == '__main__':
    sys.path.append('./extensions')
    mod = ExternalModule('mod.file')
    print( mod.Run() )

#--------------------------------
# ./extensions/mod/file.py
from .helper import Helper
class Extension:
    def method(self):
        return Helper.function()

#--------------------------------
# ./extensions/mod/helper.py
class Helper:
    def function():
        return 1
 

Это прекрасно работает с

 $ python3 ./pymodules.py 
1
 

Теперь у меня появилось новое требование, согласно которому мне нужно загружать расширения из определенного каталога, и этот каталог может измениться. Я хотел бы ограничить свои изменения pymodules.py . Я почти достигаю этого с помощью:

 # ./pymodules.py
import importlib, sys

class ExternalModule:
    def __init__(self, module_path):
        sys.dont_write_bytecode = True
        try:
            spec = importlib.util.spec_from_file_location('mod.file', module_path)
            module = importlib.util.module_from_spec(spec)
            spec.loader.exec_module(module)
            self.instance = module.Extension()
        except Exception as e:
            print('Couldn't load extension at '   module_path   ':', e)

    def Run(self):
        if hasattr(self, 'instance'):
            return self.instance.method()

if __name__ == '__main__':
    mod = ExternalModule('./path1/mod/file.py')
    print( mod.Run() )

    mod = ExternalModule('./path2/mod/file.py')
    print( mod.Run() )

    mod = ExternalModule('./path3/mod/file.py')
    print( mod.Run() )

#--------------------------
# ./path1/mod/file.py
class Extension:
    def method(self):
        return 1

#--------------------------
# ./path2/mod/file.py
class Extension:
    def method(self):
        return 2

#--------------------------
# ./path3/mod/file.py
from .helper import Helper
class Extension:
    def method(self):
        return Helper.function()

#--------------------------
# ./path3/mod/helper.py
class Helper:
    def function():
        return 3
 

But from .helper import Helper fails to load in path3 :

 $ python3 ./pymodules.py 
1
2
Couldn't load extension at ./path3/mod/file.py: No module named 'mod'
None
 

Как я могу это решить?