2008-10-17 23 views

Respuesta

52

A partir de los documentos de pitón en __import__:

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

...

Cuando la variable es el nombre de la package.module forma , normalmente, el paquete de nivel superior (la nombre hasta el primer punto) se devuelve, no el módulo nombrado por nombre. Sin embargo, cuando se proporciona un argumento de lista no vacío, se devuelve el módulo nombrado por nombre. Esto se hace para la compatibilidad con el bytecode generado para el diferentes tipos de instrucción de importación; al usar "import spam.ham.eggs", el paquete de nivel superior se debe colocar en el espacio de nombre de importación, pero cuando usando "from spam.ham import eggs", se debe usar el subpaquete spam.ham a encuentra los huevos variables. Como una solución alternativa para este comportamiento, use getattr() para extraer los componentes deseados. Por ejemplo, se puede definir la siguiente ayudante:

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

Parafraseando:

Cuando pide somepackage.somemodule, __import__ vuelve somepackage.__init__.py, lo cual es a menudo vacío.

Se volverá somemodule si proporciona fromlist (una lista de los nombres de las variables somemodule que desee, que no se devuelven en realidad)

También puede, como lo hice, utilice la función que sugieren.

Nota: Hice esta pregunta totalmente con la intención de responderla yo mismo. Hubo un gran error en mi código, y después de haberlo diagnosticado mal, me tomó mucho tiempo resolverlo, así que pensé que ayudaría a la comunidad SO y publicaría el gotcha con el que me encontré aquí.

7

Hay algo que funcione como usted quiere que: 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'> 
+0

que es muy útil, sin embargo yo realmente no tengo ninguna otra necesidad de retorcido en mi programa. Aunque, como fundador (!), Probablemente conozcas más las posibilidades que yo (nunca lo usaste). – dwestbrook

32

Python 2.7 tiene importlib, caminos de puntos se resuelven como se esperaba

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

También hay un paquete Python 2.6 que respalda esta funcionalidad. https://pypi.python.org/pypi/importlib/ – melinath

1

para Python 2.6, he escrito este fragmento:

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 
16

Existe una solución más simple, como se explica en la documentación:

Si simplemente desea importar un módulo (potencialmente dentro de un paquete) por nombre, puede llamar a __import __() y luego buscarlo en el sistema.módulos:

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

La forma en que lo hice es

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

entonces puedo acceder a cualquier contenido de por

foobar.functionName() 
+1

¿Por qué no simplemente 'foo.bar' en ese punto? –

Cuestiones relacionadas