2010-11-03 14 views
10

No estaba claro cómo nombrar correctamente esta pregunta.Prioridad de importación Python: ¿paquetes o módulos?

Caso 1

Supongamos que tengo la siguiente estructura de directorios.

foo 
| 
+- bar/__init__.py 
| 
+- bar.py 

Si tengo

from foo import bar 

¿Cómo sé qué barra (bar.py o bar/__init__.py) se importa? ¿Hay alguna manera fácil de detectar esto automáticamente?

Caso 2

foo 
| 
+- foo.py 
| 
+- other.py 

Si other.py tiene la línea

import foo 

¿Cómo sé cual foo (foo o foo.foo) se importa? De nuevo, ¿hay alguna forma fácil de detectar automáticamente que esto ocurra?

+2

manera fácil de detectarlo: tienen la primera línea de bar.py ser 'impresión (" barra .py importado ")' – nmichaels

+2

Debería tener RTFM-ed. http://docs.python.org/tutorial/modules.html es un gran recurso. –

+0

¿Hay alguna manera de forzar al programa a usar una interpretación u otra? – Sobi

Respuesta

6

TLDR; un paquete tiene prioridad sobre un módulo del mismo nombre si están en el mismo directorio.

A partir de los documentos:

"Cuando un módulo denominado spam es importado, las búsquedas de intérprete para un archivo llamado spam.py en el directorio actual, y luego en el listado de directorios especificados por la variable de entorno PYTHONPATH. Tiene la misma sintaxis que la variable de shell PATH, es decir, una lista de nombres de directorio ".

Esto es un poco engañoso porque el intérprete también buscará un paquete llamado spam (un directorio llamado spam que contiene un archivo __init__.py). Dado que las entradas del directorio se ordenan antes de la búsqueda, los paquetes tienen prioridad sobre los módulos con el mismo nombre si están en el mismo directorio porque spam viene antes de spam.py.

Tenga en cuenta que el "directorio actual" es relativo a la ruta del script principal (aquel en el que __name__ == '__main__' is True). Por lo tanto, si se encuentra en /home/billg llamando al /foo/bar.py, "directorio actual" se refiere a /foo.

+1

¿Han cambiado las cosas? porque no parece que se agregue el directorio actual como sugieres. Los documentos ahora dicen: "Cuando se importa un módulo llamado spam, el intérprete primero busca un módulo integrado con ese nombre. Si no se encuentra, busca un archivo llamado spam.py en una lista de directorios dados por el variable sys.path ". Y no veo que el "directorio actual" esté en la lista. Pero dado que estoy perdido, tal vez estoy malentendido? – PatrickT

+1

Y (podría estar malinterpretando todo esto) una respuesta anterior de stackoverflow dice: "Python no agrega el directorio actual a sys.path, sino el directorio en el que se encuentra el script". http://stackoverflow.com/questions/2325923/how-to-fix-importerror-no-module-named-error-in-python – PatrickT

+0

Esto no parece responder ** Caso 1 ** – qff

0

en el primer caso que estamos tratando de importar la barra de funciones de archivo 'foo.py'

En el segundo que está tratando de importar el archivo 'foo.py'

2

Paquetes (directorios con __init__.py) tienen prioridad sobre los módulos. La documentación de este hecho es difícil de encontrar, pero puede ver esto en la fuente: python 2.7, python 3.6 (gracias @qff por el hallazgo).

También necesitará un __init__.py dentro del directorio foo para que su ejemplo funcione.

Si other.py está dentro de foo/ entonces se cargue foo.py (no el directorio foo/), ya que se verá en el directorio actual en primer lugar (a menos que hayas jugado con PYTHONPATH o sys.path).

+0

¿Cómo sabes que tiene prioridad? - No pude encontrarlo en [la documentación de Python] (https://docs.python.org/2/tutorial/modules.html) – qff

+0

@qff Lo probé. También probé python3 justo ahora y tiene el mismo comportamiento. Un enlace a la documentación oficial del hecho sería bueno. Si encuentra uno, siéntase libre de editar mi respuesta o publicar un comentario y lo editaré. – kanaka

+0

¡Lo encontré! (tipo de): las entradas de un directorio se ordenan antes de intentar cargar cada una como un paquete o módulo. Esto asegura que los paquetes se carguen primero. [Enlace al código fuente CPython] (https://github.com/python/cpython/blob/c30098c8c6014f3340a369a31df9c74bdbacc269/Lib/pkgutil.py#L235) – qff

5

de una concha de pitón:

from foo import bar 

print bar.__file__ 

debería decirle qué archivo se ha importado

Rob

+0

no tiene atributo __file__ en python3 – gabn88

Cuestiones relacionadas