Подтвердить что ты не робот

Python __import__ не работает должным образом

При использовании __import__ с точным именем, например: somepackage.somemodule, возвращаемый модуль не является somemodule, все, что возвращается, кажется, в основном пустым! что здесь происходит?

4b9b3361

Ответ 1

В документах python на __import__:

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

...

Если переменная name имеет форму package.module, как правило, пакет высшего уровня (название до первая точка), а не модуль по имени. Однако, когда дается непустой аргумент fromlist, возвращается модуль с именем по имени. Это делается для совместимости с байт-код, сгенерированный для различные виды импортных заявлений; при использовании "import spam.ham.eggs", должен быть размещен спам пакета верхнего уровня в импорте пространства имен, но когда используя "из spam.ham import eggs", Подпапка spam.ham должна использоваться для найдите переменные яйца. Как обходной путь для этого поведения, использование 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-сообществу и опубликую полученную здесь информацию.

Ответ 2

python 2.7 имеет importlib, точечные пути разрешают, как ожидалось

import importlib
foo = importlib.import_module('a.dotted.path')
instance = foo.SomeClass()

Ответ 3

Существует более простое решение, как описано в документации:

Если вы просто хотите импортировать модуль (потенциально внутри пакета) по имени, вы можете вызвать __import __(), а затем просмотреть его в sys.modules:

>>> import sys
>>> name = 'foo.bar.baz'
>>> __import__(name)
<module 'foo' from ...>
>>> baz = sys.modules[name]
>>> baz
<module 'foo.bar.baz' from ...>

Ответ 4

Есть что-то, что работает так, как вы хотите: 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'>

Ответ 5

Для 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

Ответ 6

Как я это сделал,

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

то я могу получить доступ к любому контенту с помощью

foobar.functionName()