Módulos, Paquetes e Imports en Python¶
Módulos en python¶
Un módulo es un archivo .py con código Python.
Ejemplo:
Podemos importar su contenido desde otro archivo que esté en la misma carpeta:
Cuando haces import, Python busca el archivo .py con ese nombre.
Paquetes¶
Un paquete es una carpeta que contiene módulos y un archivo especial llamado __init__.py.
Esto permite importar con una ruta jerárquica:
El archivo __init__.py indica que la carpeta es un paquete importable.
Paquetes y subpaquetes¶
Si tenemos esta estructura:
biblioteca/
├── __init__.py
├── domain/
│ ├── __init__.py
│ ├── libro.py
│ └── repositorio_libros.py
hace que Python reconozca:
bibliotecacomo un paquete,biblioteca.domaincomo un subpaquete,biblioteca.domain.librocomo un módulo.
__init.py__¶
Como hemos visto, en Python, una carpeta solo se considera un paquete importable si contiene un archivo llamado __init__.py.
Si no hay un __init__.py, Python no sabrá que esa carpeta forma parte del paquete, y los imports como from biblioteca.domain.libro import Libro fallarán (a menos que uses namespace packages, que es un tema más avanzado).
El archivo __init__.py:
- Puede estar vacío.
- O puede ejecutar código al importar el paquete.
- También puede usarse para exponer elementos del paquete.
Ejemplo:
Entonces la clase Libro se puede importar así:
biblioteca.domain, carga su __init__.py
y revisa qué nombres están definidos allí.
Como dentro del __init__.py se importó Libro, entonces Libro ya está disponible como parte del paquete.
Esto se hace para simplificar los imports y definir qué símbolos “públicos” ofrece el paquete.
El sys.path¶
sys.path es una lista de rutas donde Python busca módulos.
Puede consultarse con:
Cuando ejecutas:
Python añade la carpeta que contiene biblioteca/ a sys.path, por eso los imports absolutos funcionan.
Funcionamiento de import¶
Cuando escribes:
Python hace lo siguiente:
- Busca en
sys.path(una lista de rutas donde busca módulos). - Encuentra la carpeta que contiene
biblioteca/. - Entra en
biblioteca/y busca el archivolibro.py. - Ejecuta el código de
libro.py(si no se ha ejecutado antes) y carga la claseLibroen memoria.
Tipos de imports¶
a) Import absoluto (recomendado)¶
Importa desde la raíz del paquete.
Es la forma más clara y segura.
b) Import relativo¶
Usa puntos para moverse entre carpetas dentro del mismo paquete.
.→ mismo nivel..→ subir un nivel...→ subir dos niveles
Solo funciona si se ejecuta el proyecto como módulo con -m, por ejemplo:
c) Error común: ejecutar desde dentro de la carpeta¶
Si ejecutas:
y dentro tienes:
obtendrás:
Porque al ejecutar desde dentro de biblioteca/, Python ya no la ve como paquete raíz.
Ejemplo de imports¶
Si el proyecto tiene la siguiente estructura de carpetas
biblioteca/
├── __init__.py
├── domain/
│ ├── __init__.py
│ ├── libro.py
│ └── repositorio_libros.py
├── application/
│ ├── __init__.py
│ └── servicios.py
├── infrastructure/
│ ├── __init__.py
│ └── repositorio_memoria.py
└── presentation/
├── __init__.py
└── menu.py
Imports correctos entre capas¶
De forma esquemática:
(raíz del proyecto)
│
└── biblioteca/
├── presentation/
│ └── menu.py → importa application
├── application/
│ └── servicios.py → importa domain
├── domain/
│ └── libro.py
└── infrastructure/
└── repositorio_memoria.py → importa domain
Flujo de dependencias:
| Archivo | Importaciones correctas |
|---|---|
application/servicios.py |
from biblioteca.domain.libro import Librofrom biblioteca.domain.repositorio_libros import RepositorioLibros |
infrastructure/repositorio_memoria.py |
from biblioteca.domain.repositorio_libros import RepositorioLibrosfrom biblioteca.domain.libro import Libro |
presentation/menu.py |
from biblioteca.application.servicios import ServicioBibliotecafrom biblioteca.infrastructure.repositorio_memoria import RepositorioLibrosMemoria |
Reglas generales:
- las capas superiores importan a las inferiores, nunca al revés.
- El dominio no debe importar la aplicación ni la infraestructura.
Cómo ejecutar el proyecto¶
Estando un nivel por encima de la carpeta biblioteca/, ejecuta:
Esto le dice a Python que ejecute el archivo menu.py dentro del paquete biblioteca.presentation.
Así Python sabe que biblioteca es el paquete raíz y puede resolver imports como:
Conclusión¶
Las ideas más importantes que se recogen en estos apuntes son:
| Concepto | Explicación | Ejemplo |
|---|---|---|
| Módulo | Archivo .py |
libro.py |
| Paquete | Carpeta con __init__.py |
biblioteca/domain/ |
| Import absoluto | Desde la raíz del paquete | from biblioteca.domain.libro import Libro |
| Import relativo | Con . o .. dentro del paquete |
from ..domain.libro import Libro |
| Ejecutar módulo | Forma correcta de ejecutar | python -m biblioteca.presentation.menu |
| Regla de dependencias | Las capas superiores usan las inferiores | presentation → application → domain |