60

Python では、プログラムの実行中にモジュールをパッケージに動的に追加する方法を教えてください。

外部プロセスからパッケージ ディレクトリにモジュールを追加し、それらの新しいモジュールを自分のプログラムで使用できるようにしたいと考えています。

import package

def doSomething(name):
    pkg = __import__("package." + name)
    mod = getattr(pkg, name)
    mod.doSomething()

どうすればいいですか?

4

6 に答える 6

60

あなたのコードはほぼ正しいです。

関数を参照してください__import__

def doSomething(name):
    name = "package." + name
    mod = __import__(name, fromlist=[''])
    mod.doSomething()
于 2009-06-04T15:25:02.743 に答える
23

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()

明らかに、すべての「サービス」サブフォルダー参照をパラメーターに置き換えることができます。

于 2009-06-04T16:33:38.880 に答える
9

Bastien の答えの 1 つのトリック...__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()
于 2009-06-04T17:02:57.113 に答える
3

ディレクトリへの変更を検出するには、Linux でpyinotifyを使用できます(これは、適切な作業例です)。Mac ではfsevents (Mac に付属の PyObjC パッケージ経由)。Windows では、win32api (または Python 標準ライブラリモジュール)経由のディレクトリ変更通知。私の知る限り、これらのさまざまなアプローチを 1 つのポータブル パッケージにまとめた人はいません。(もちろん、最悪の場合、Tim Golden の記事のように、定期的なポーリングなどの「低技術」のアプローチにフォールバックすることができます。おそらく、シグナルを介した「外部プロセスからのアラート」のタッチなど)。ctypes

通知と新しいモジュールまたは変更されたモジュールの名前を取得したら、質問に表示するコードが機能するはずです。

于 2009-06-04T15:26:31.943 に答える
-1

モジュール ディレクトリを追加しsys.path、通常のimportステートメントを使用します。

于 2009-06-04T15:02:24.537 に答える