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

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

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
43
0
18 942
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Из документов python на __import__:

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

...

When the name variable is of the form package.module, normally, the top-level package (the name up till the first dot) is returned, not the module named by name. However, when a non-empty fromlist argument is given, the module named by name is returned. This is done for compatibility with the bytecode generated for the different kinds of import statement; when using "import spam.ham.eggs", the top-level package spam must be placed in the importing namespace, but when using "from spam.ham import eggs", the spam.ham subpackage must be used to find the eggs variable. As a workaround for this behavior, use getattr() to extract the desired components. For example, you could define the following helper:

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 и опубликую здесь ошибку, с которой я столкнулся.

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

Это очень полезно, однако в моей программе нет никакой другой необходимости в скручивании. Хотя, как основатель (!), Вы, наверное, лучше меня осведомлены о возможностях (никогда этим не пользовались).

dwestbrook 18.10.2008 23:40

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

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

Также существует пакет python 2.6, который поддерживает эту функциональность. pypi.python.org/pypi/importlib

melinath 15.03.2013 01:03

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

Как объясняется в документации, есть более простое решение:

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

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

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

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

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

foobar.functionName()

Другие вопросы по теме