実装モジュールを切り替えるモジュール
昨日のコードをモジュール化する
try except ImportErrorとか多い書く人にはいいかも知れないな
modinstaller.py
from abc import ABCMeta, abstractmethod import sys def install(imports, *args, **kwargs): global _mod_name, _imports local = sys._getframe(1).f_locals _mod_name = local['__name__'] _imports = imports _search(*args, **kwargs) class Installer(object): __metaclass__ = ABCMeta @classmethod def install(cls, *args, **kwargs): i = cls(*args, **kwargs) _install(i) def _install(obj): names = _mod_name.split('.') if sys.modules.get(_mod_name, None): del sys.modules[_mod_name] try: mod = __import__('.'.join(names[:-1])) mod.__dict__[names[-1]] = obj except ImportError: pass sys.modules[_mod_name] = obj def _search(*args, **kwargs): for name in _imports: try: names = name.split('.') imp_name = '.'.join(names[:-1]) nm = __import__(imp_name) mod_name = imp_name.split('.')[-1] mod = getattr(nm, mod_name, None) if mod: obj = getattr(mod ,names[-1], None) if obj and issubclass(obj, Installer): return obj.install(*args, **kwargs) except ImportError: pass
使い方
仕込みたいモジュールに
- importするクラスの配列
を書く
実装クラスは
- Installerクラスのサブクラスであること
例:
example/engine1.py
import modinstaller class Engine(modinstaller.Installer): def method(self): print("engine1 call")
example/engine2.py
import modinstaller class Engine(modinstaller.Installer): def method(self): print("engine2 call")
example/engine.py
import modinstaller imports = ['example.engine1.Engine', 'example.engine2.Engine'] modinstaller.install(imports)
example.engineをimportするとEngineクラスが使えるようにする。
実装クラスは配列の先頭からimportしていきimportできた時点で止まる。