2012-01-28 9 views
49

probablemente estoy perdiendo algo obvio, pero de todos modos:paquetes de importación de Python

Al importar un paquete como os en Python, se puede utilizar cualquier submódulos/sub-paquetes fuera de la apuesta. Por ejemplo, esto funciona:

>>> import os 
>>> os.path.abspath(...) 

Sin embargo tengo mi propio paquete que está estructurado de la siguiente manera:

FooPackage/ 
    __init__.py 
    foo.py 

y aquí la misma lógica no funciona:

>>> import FooPackage 
>>> FooPackage.foo 
AttributeError: 'module' object has no attribute 'foo' 

¿Qué soy yo haciendo mal?

Respuesta

29

es necesario importar el submódulo:

import FooPackage.foo 

Lo que estás haciendo está buscando foo en FooPackage/__init__.py. Puede resolverlo poniendo import FooPackage.foo as foo (o from . import foo) en FooPackage/__init__.py, luego Python podrá encontrar foo allí. Pero recomiendo usar mi primera sugerencia.

+4

Según entendí, la pregunta no era cómo importar un submódulo, era por eso que se podía acceder a un submódulo de os sin importar ese submódulo, y cómo implementar algo similar. Editar: Sin embargo, su respuesta funcionaría – pycoder112358

55

Al importar FooPackage, Python busca en los directorios en PYTHONPATH hasta que encuentra un archivo llamado FooPackage.py o un directorio llamado FooPackage que contiene un archivo llamado __init__.py. Sin embargo, al haber encontrado el directorio del paquete, lo hace , no, luego escanea ese directorio e importa automáticamente todos los archivos .py.

Existen dos motivos para este comportamiento. El primero es que la importación de un módulo ejecuta código Python que puede llevar tiempo, memoria o tener efectos secundarios. Por lo tanto, es posible que desee importar a.b.c.d sin importar necesariamente todo un gran paquete a. Depende del diseñador del paquete decidir si a __init__.py importa explícitamente sus módulos y subpaquetes para que estén siempre disponibles, o si deja al programa cliente la posibilidad de seleccionar y elegir lo que se carga.

El segundo es un poco más sutil, y también sorprendente. Sin una instrucción explícita de importación (ya sea en FooPackage/__init__.py o en el programa cliente), Python no necesariamente sabe qué nombre debería importar foo.py como. En un sistema sensible a mayúsculas archivo (tal como se utiliza en Windows), esto podría representar un módulo denominado foo, Foo, FOO, fOo, foO, FoO, FOo o fOO. Todos estos son identificadores de Python válidos y distintos, por lo que Python simplemente no tiene suficiente información del archivo solo para saber a qué te refieres. Por lo tanto, para comportarse de manera consistente en todos los sistemas, se requiere una declaración de importación explícita en alguna parte para aclarar el nombre, incluso en sistemas de archivos donde la información de caso completo está disponible.

9

Necesita agregar from . import foo al archivo __init__.py en su paquete.

+1

(Esta información estaba en las otras respuestas ya publicadas, pero tenía que leerla un poco. Así que la publiqué nuevamente como una respuesta simple a la pregunta.) –

+0

Mejor usar el '__all__ = [" foo "]' en su lugar –

-1

Puede importar un paquete desde la biblioteca mediante la instrucción de importación.

sintaxis: module_name importación

 ex: import math 

Puede importar sólo un método específico formar un paquete utilizando la sintaxis golpe

sintaxis: desde module_name function_name importación

 ex: from math import radians 
1

Hay algunos conceptos erróneos importantes que deben abordarse, específicamente con la terminología. Primero, generalmente, cuando piensas que estás importando un package en python, lo que estás realmente importando es un module. Debería usar el término package cuando piense en términos de subestructura del sistema de archivos que lo ayude a organizar su código. Pero desde la perspectiva del código, cada vez que importa un package, Python lo trata como un módulo. Todos los paquetes son módulos. No todos los módulos son paquetes. Un módulo con el atributo __path__ se considera un paquete.

Puede verificar que os es un módulo. Para confirmar esto se puede hacer:

import os 
print(type(os)) # will print: <type 'module'> 

En su ejemplo, cuando se hace import FooPackage, FooPackage se trata y se considera que es un módulo también, y sus atributos (funciones, clases, etc.) están supuestamente define en __init__.py . Como su __init__.py está vacío, no puede encontrar foo.

Fuera de las declaraciones import no se puede usar la notación '.' para direccionar los módulos dentro de los módulos. La única excepción ocurre si se importa un archivo module en el paquete del padre previsto __init__.py. Para que quede claro, vamos a hacer algunos ejemplos aquí:

Tenga en cuenta su estructura original:

FooPackage/ 
    __init__.py 
    foo.py 

Caso 1: __init__.py es un archivo vacío

#FooPackage imported as a module 
import FooPackage 

#foo is not a name defined in `__init__.py`. Error 
FooPackage.foo 

#FooPackage.foo imported as a module 
import FooPackage.foo 

#Error, foo has not been imported. To be able to use foo like this, 
#you need to do: import FooPackage.foo as foo 
foo.anything 

#Not error, if anything is defined inside foo.py 
FooPackage.foo.anything 

Caso 2: __init__.py tiene la línea import foo en él:

import FooPackage 

#Now this is good. `foo` is sort of considered to be an attribute of 
#FooPackage 
FooPackage.foo 

Supongamos que foo ya no es un module, sino un function que usted define en __init__.py. si lo hace import FooPackage.foo, arrojará un error diciendo que foo no es un módulo.

Cuestiones relacionadas