Frage

Wenn __import__ mit einem gepunkteten Namen, so etwas wie: somepackage.somemodule, kehrte das Modul nicht somemodule ist, was zurückgegeben wird, scheint meistens leer zu sein! was hier los?

War es hilfreich?

Lösung

Von dem Python-docs auf __import__:

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

...

     

Wenn der Name Variable ist von der Form   package.module normalerweise das   Top-Level-Paket (der Name bis   der erste Punkt) zurückgegeben wird, nicht die   Modul mit Namen genannt. Wenn jedoch ein   nicht leere fromlist Argument gegeben wird,   das Modul mit Namen genannt wird zurückgegeben.   Dies ist für die Kompatibilität getan mit   der Bytecode für die erzeugten   verschiedene Arten von Import-Anweisung;   bei der Verwendung von „import spam.ham.eggs“, die   Top-Level-Paket Spam muss gestellt werden   im Importnamespace, aber wenn   Verwendung „von spam.ham Import Eier“, die   spam.ham subpackage muss verwendet werden,   finden die Eier variabel. Als ein   Abhilfe für dieses Verhalten, Nutzung   getattr () zu extrahieren, die gewünschte   Komponenten. Zum Beispiel könnten Sie   definiert die folgenden Helfer:

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

paraphrasieren:

Wenn Sie sich für somepackage.somemodule fragen, __import__ gibt somepackage.__init__.py, die oft leer ist.

Es wird wieder somemodule wenn Sie fromlist (eine Liste der Variablennamen innerhalb somemodule Sie wollen, die nicht tatsächlich zurückgegeben) liefern

Sie können auch, wie ich es tat, verwenden Sie die Funktion, die sie vorschlagen.

Hinweis: Ich habe diese Frage voll, es selbst zu beantworten beabsichtigt. Es war ein großer Fehler in meinem Code, und es falsch diagnostiziert zu haben, es dauerte eine lange Zeit, um herauszufinden, so dass ich dachte ich das SO Gemeinschaft helfen würde und poste Gotcha ich in hier lief.

Andere Tipps

Python 2.7 hat importlib, punktierte Pfade aufzulösen wie erwartet

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

Es gibt eine einfachere Lösung, wie in der Dokumentation erläutert:

Wenn Sie wollen einfach nur ein Modul importieren (möglicherweise in einem Paket) mit Namen, können Sie rufen __import __ () und es dann in sys.modules nachschlagen:

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

Es ist etwas, das funktioniert, wie Sie es wollen: 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'>

Für Python 2.6, Ich schrieb dieses Snippet:

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

So wie ich das tat, ist

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

dann kann ich alle Inhalte zugreifen, indem

foobar.functionName()
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top