2009-06-29 13 views
15

Tengo una carpeta de mensajes (paquete) con el archivo __init__.py y otro módulo messages_en.py dentro de él. En __init__.py si importo messages_en funciona, pero __import__ falla con "ImportError: Ningún módulo llamado messages_en"¿Cómo puedo importar un paquete usando __import __() cuando el nombre del paquete solo se conoce en tiempo de ejecución?

import messages_en # it works 
messages = __import__('messages_en') # it doesn't ? 

Yo solía pensar que 'importación x' es sólo otra forma de decir __import__('x')

Respuesta

14

Añadiendo el argumento globales es suficiente para mí:

__import__('messages_en', globals=globals()) 

De hecho, sólo __name__ es Necesario aquí:

__import__('messages_en', globals={"__name__": __name__}) 
14

__import__ es una función interna llamada por declaración de importación. En todos los días de codificación que no necesita (o quiere) para llamar __import__

de documentación de Python:

Por ejemplo, la declaración import spam resultados en código de bytes que se asemejan el siguiente código:

spam = __import__('spam', globals(), locals(), [], -1) 

Por otra parte, la afirmación from spam.ham import eggs, sausage as saus resultados en

_temp = __import__('spam.ham', globals(), locals(), ['eggs', 'sausage'], -1) 
eggs = _temp.eggs 
saus = _temp.sausage 

más información: http://docs.python.org/library/functions.html

+1

1 y gracias por la explicación, pero ¿podría describir exactamente qué El ejemplo de OP no funciona? Parece que intenta aliar mensajes_en mensajes, lo que me parece (ingenuamente) razonable. –

+0

Como 'wr' explicó que era debido al nivel, y sé que __import__ no debería usarse normalmente, pero en este caso tengo que leer dinámicamente el lenguaje de un archivo de configuración adjuntar a mensajes e importar ese archivo –

+0

Este ejemplo fue muy útil, especialmente si intenta cargar módulos desde subdirectorios. Me ayudó a corregir el error "Atributo no encontrado". – Carlos

19

Si se trata de un problema del camino, se debe utilizar el argumento level (de docs):

__import__(name, globals={}, locals={}, fromlist=[], level=-1) -> module 

Level is used to determine whether to perform 
absolute or relative imports. -1 is the original strategy of attempting 
both absolute and relative imports, 0 is absolute, a positive number 
is the number of parent directories to search relative to the current module. 
+2

pero me pregunto cuál fue la razón, porque el nivel predeterminado es -1, y todavía estoy pasando -1, así que solo son dict globales/locales, cómo eso hace la diferencia –

+0

¿Por qué es esta la respuesta aceptada? No responde la pregunta ni arregla el problema. – kynan

+0

Esta respuesta es incorrecta. El problema de OP no está relacionado con 'nivel' de ninguna manera. Dos opciones para solucionarlo: o bien suministre los valores globales del módulo como 'messages = __import __ ('messages_en', globals())' como señala Eric o proporcione el nombre del paquete como sugiere Lennart. – kynan

0

Usted podría intentar esto:

messages == __import__('Foo.messages_en', fromlist=['messages_en']) 
3

asegúrese de añadir el directorio de módulos a tu camino de python.

Su ruta (la lista de directorios por los que pasa Python para buscar módulos y archivos) se almacena en el atributo de ruta del módulo sys. Como la ruta es una lista, puede usar el método de agregar para agregar nuevos directorios a la ruta.

Por ejemplo, para agregar el directorio/home/me/mypy a la ruta:

import sys 
sys.path.append("/home/me/mypy") 
+1

Eso no es seguro ya que hace que el paquete no sea reubicable. Solo funcionará si el paquete está en esta ruta codificada. – kynan

0

Debe importar manualmente el paquete superior de la ruta del paquete dinámico.

Por ejemplo, en el principio del archivo que escribo:

import sites 

luego en este código funciona para mí:

target = 'some.dynamic.path' 
my_module = __import__ ('sites.%s.fabfile' % target, fromlist=["sites.%s" % target]) 
Cuestiones relacionadas