#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
Как я могу это решить?