2009-01-19 15 views
64

Parece que Python no puede importar un módulo en una subcarpeta. Aparece el error cuando trato de crear una instancia de la clase desde el módulo importado, pero la importación en sí misma tiene éxito. Aquí está mi estructura de directorios:No se puede obtener Python para importar desde una carpeta diferente

Server 
    -server.py 
    -Models 
     --user.py 

Aquí está el contenido de server.py:

from sys import path 
from os import getcwd 
path.append(getcwd() + "\\models") #Yes, i'm on windows 
print path 
import user 

u=user.User() #error on this line 

Y user.py:

class User(Entity): 
    using_options(tablename='users') 

    username = Field(String(15)) 
    password = Field(String(64)) 
    email = Field(String(50)) 
    status = Field(Integer) 
    created = Field(DateTime) 

El error es: AttributeError: 'módulo' objeto no tiene atributo 'Usuario'

+1

¿Puedes pegar el mensaje de error? –

Respuesta

96

Creo que necesita crear un archivo llamado __init__.py en el directorio de Modelos para que python lo trate como un módulo.

entonces usted puede hacer:

from Models.user import User 

Puedes incluir código en el (código de inicialización por ejemplo, que algunas clases diferentes necesitan) __init__.py o dejarlo en blanco. Pero debe estar allí.

+1

Gracias, nunca había oído hablar de paquetes antes de esto. – ryeguy

+0

En realidad, al importar Python, trata a blah.py y blah/__ init__.py exactamente igual. –

+1

Eso no fue evidente ... Y me digo a mí mismo: RTFM FMF –

20

Tienes que crear __init__.py en la subcarpeta Models. El archivo puede estar vacío. Define un paquete.

entonces usted puede hacer:

from Models.user import User 

leer toda la información en el tutorial del pitón, here.

También hay un buen artículo sobre la organización de archivos de los proyectos de python here.

+0

¿Qué sucede si el archivo NO está vacío? – darkgaze

7

Te has perdido __init__.py. Desde el tutorial de Python:

The __init__.py files are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path. In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable, described later.

Deja un archivo vacío llamado __init__.py en el directorio de modelos, y todos deben ser de oro.

10

import user

u=user.User() #error on this line

Debido a la falta de __init__ se mencionó anteriormente, se puede esperar un ImportError lo que haría que el problema más clara.

No lo obtiene porque 'usuario' también es un módulo existente en la biblioteca estándar. Su instrucción de importación toma esa y trata de encontrar la clase de Usuario dentro de ella; eso no existe y solo entonces obtienes el error.

Es generalmente una buena idea para hacer su importación absoluta:

import Server.Models.user 

para evitar este tipo de ambigüedad. De hecho, desde Python 2.7 'usuario de importación' no se verá en absoluto en relación con el módulo actual.

Si realmente quieres importaciones relativas, puedes tenerlas explícitamente en Python 2.5 y hasta utilizando el algo feo sintaxis:

from .user import User 
6

La forma correcta para importar un módulo ubicado en una carpeta principal, cuando usted no tiene una estructura de paquete estándar, es:

import os, sys 
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) 
sys.path.append(os.path.dirname(CURRENT_DIR)) 

(puedes unir las dos últimas líneas, pero de esta manera es más fácil de entender).

Esta solución es multiplataforma y es lo suficientemente general para no tener que modificarla en otras circunstancias.

0

La solución de glarrain funciona mejor. Me encontré con el problema de que Python no podía reconocer mis módulos de python y me dio un error de 'módulo no encontrado'. Para mí, incluso después de agregar los archivos __init__.py e importar los módulos de manera apropiada, sigo teniendo el mismo error. Resolví el problema siguiendo la respuesta de glarrain.

+0

Esto podría haber sido un comentario sobre su respuesta en el mejor de los casos. – Ben

1

¿cómo se escribe los parámetros os.path.dirname .... comando?

import os, sys 
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) 
sys.path.append(os.path.dirname(CURRENT_DIR)) 
0

Mi forma preferida es tener __init__.py en cada directorio que contiene los módulos que se acostumbra por otros módulos, y en el punto de entrada, anular sys.path de la siguiente manera:

def get_path(ss): 
    return os.path.join(os.path.dirname(__file__), ss) 
sys.path += [ 
    get_path('Server'), 
    get_path('Models') 
] 

Este hace que los archivos en directorios especificados sean visibles para la importación, y puedo importar usuarios desde Server.py.

Cuestiones relacionadas