43

ドット付きの名前で使用__import__すると、次のようになります: somepackage.somemodule、返されるモジュールは isn ではなくsomemodule、返されるものはほとんど空のようです! 何が起きてる?

4

6 に答える 6

54

のpythonドキュメントから__import__

__import__( name[, globals[, locals[, fromlist[, level]]]])

...

name 変数が package.module の形式の場合、通常、名前で指定されたモジュールではなく、最上位パッケージ (最初のドットまでの名前) が返されます。ただし、空でない fromlist 引数が指定された場合は、名前で指定されたモジュールが返されます。これは、さまざまな種類の import ステートメント用に生成されたバイトコードとの互換性のために行われます。「import spam.ham.eggs」を使用する場合、最上位パッケージの spam をインポートする名前空間に配置する必要がありますが、「from spam.ham import eggs」を使用する場合は、spam.ham サブパッケージを使用して、egg 変数を見つける必要があります。 . この動作の回避策として、getattr() を使用して目的のコンポーネントを抽出します。たとえば、次のヘルパーを定義できます。

def my_import(name):
    mod = __import__(name)
    components = name.split('.')
    for comp in components[1:]:
        mod = getattr(mod, comp)
    return mod

言い換えると:

を求めるとsomepackage.somemodule__import__が返されますがsomepackage.__init__.py、これは多くの場合空です。

提供すると返されsomemoduleます(実際には返されない、必要fromlistな内部の変数名のリスト)somemodule

私が行ったように、彼らが提案する機能を使用することもできます。

注:私は自分で答えるつもりでこの質問をしました。私のコードには大きなバグがあり、それを誤診したため、それを理解するのに長い時間がかかったので、SO コミュニティを助けて、ここに出くわした落とし穴を投稿することにしました。

于 2008-10-17T04:46:20.680 に答える
32

Python 2.7 には importlib があり、ドット パスは期待どおりに解決されます

import importlib
foo = importlib.import_module('a.dotted.path')
instance = foo.SomeClass()
于 2011-02-28T06:08:46.463 に答える
16

ドキュメントで説明されているように、より簡単な解決策があります。

モジュール(場合によってはパッケージ内)を名前でインポートするだけの場合は、__ import __()を呼び出して、sys.modulesで検索できます。

>>> import sys
>>> name = 'foo.bar.baz'
>>> __import__(name)
<module 'foo' from ...>
>>> baz = sys.modules[name]
>>> baz
<module 'foo.bar.baz' from ...>
于 2011-08-05T13:54:49.350 に答える
7

あなたが望むように動作するものがありますtwisted.python.reflect.namedAny::

>>> from twisted.python.reflect import namedAny
>>> namedAny("operator.eq")
<built-in function eq>
>>> namedAny("pysqlite2.dbapi2.connect")
<built-in function connect>
>>> namedAny("os")
<module 'os' from '/usr/lib/python2.5/os.pyc'>
于 2008-10-18T06:37:19.113 に答える
1

Python 2.6の場合、私は次のスニペットを作成しました。

def import_and_get_mod(str, parent_mod=None):
    """Attempts to import the supplied string as a module.
    Returns the module that was imported."""
    mods = str.split('.')
    child_mod_str = '.'.join(mods[1:])
    if parent_mod is None:
        if len(mods) > 1:
            #First time this function is called; import the module
            #__import__() will only return the top level module
            return import_and_get_mod(child_mod_str, __import__(str))
        else:
            return __import__(str)
    else:
        mod = getattr(parent_mod, mods[0])
        if len(mods) > 1:
            #We're not yet at the intended module; drill down
            return import_and_get_mod(child_mod_str, mod)
        else:
            return mod
于 2011-03-30T17:07:40.503 に答える
0

私がした方法は

foo = __import__('foo',  globals(), locals(), ["bar"], -1)
foobar = eval("foo.bar")

その後、私はからのコンテンツにアクセスできます

foobar.functionName()
于 2014-08-19T11:11:58.347 に答える