pythonでは、プログラムの実行中にモジュールをパッケージに動的に追加する方法を教えてください。
外部プロセスからパッケージディレクトリにモジュールを追加し、プログラムでそれらの新しいモジュールを使用できるようにしたい:
import package
def doSomething(name):
pkg = __import__("package." + name)
mod = getattr(pkg, name)
mod.doSomething()
どうすればいいですか?
コードはほぼ正しいです。
見る - __import__
関数。
def doSomething(name):
name = "package." + name
mod = __import__(name, fromlist=[''])
mod.doSomething()
Bastienはすでに質問に答えていましたが、とにかく辞書のサブフォルダーからすべてのモジュールをロードするために私が使用するこの関数は便利です:
def loadModules():
res = {}
import os
# check subfolders
lst = os.listdir("services")
dir = []
for d in lst:
s = os.path.abspath("services") + os.sep + d
if os.path.isdir(s) and os.path.exists(s + os.sep + "__init__.py"):
dir.append(d)
# load the modules
for d in dir:
res[d] = __import__("services." + d, fromlist = ["*"])
return res
もう1つは、最初の関数によってロードされたモジュールの1つで定義されたクラスによってオブジェクトをインスタンス化することです。
def getClassByName(module, className):
if not module:
if className.startswith("services."):
className = className.split("services.")[1]
l = className.split(".")
m = __services__[l[0]]
return getClassByName(m, ".".join(l[1:]))
Elif "." in className:
l = className.split(".")
m = getattr(module, l[0])
return getClassByName(m, ".".join(l[1:]))
else:
return getattr(module, className)
これらの関数を使用する簡単な方法は次のとおりです。
mods = loadModules()
cls = getClassByName(mods["MyModule"], "submodule.filepy.Class")
obj = cls()
明らかに、すべての「services」サブフォルダー参照をパラメーターに置き換えることができます。
import importlib
module = importlib.import_module('my_package.my_module')
my_class = getattr(module, 'MyClass')
my_instance = my_class()
Bastienの答えのコツ... __import__()
関数は、モジュールオブジェクトではなくパッケージオブジェクトを返します。次の関数を使用すると、パッケージからモジュールが動的にロードされ、パッケージではなくモジュールが返されます。
def my_import(name):
mod = __import__(name)
components = name.split('.')
for comp in components[1:]:
mod = getattr(mod, comp)
return mod
その後、次のことができます。
mod = my_import('package.' + name)
mod.doSomething()
ディレクトリの変更を検出するには、Linuxで pyinotify を使用できます(- here は素晴らしい動作例です); Macでは fsevents (Macに付属のPyObjCパッケージ経由); Windowsでは、 ディレクトリ変更通知win32api 経由(またはPython標準ライブラリctypes
モジュール)。これらのさまざまなアプローチを1つのポータブルパッケージにアップします(もちろん、最悪の場合、 Tim Goldenの記事 のように、定期的なポーリングなどの「ローテク」アプローチにフォールバックできます。外部プロセスから」などのシグナルを介して)。
通知と新しいモジュールまたは変更されたモジュールの名前を取得したら、質問に表示されるコードが機能するはずです。