Módulos y Paquetes de Python
Este documento explora el concepto de módulos y paquetes en Python, dos elementos fundamentales que permiten organizar y reutilizar el código de manera eficiente. A través de ejemplos y explicaciones claras, se abordarán las diferencias entre módulos y paquetes, así como su creación y uso en proyectos de programación.

¿Qué es un Paquete y un Módulo?
Paquete
Un paquete es una colección de módulos organizados dentro de un directorio. Este directorio debe incluir un archivo especial llamado __init__.py
, que indica a Python que el directorio es un paquete, Si no se necesita lógica específica, el archivo puede estar vacío. Esto es suficiente para que Python trate al directorio como un paquete. pero es buena práctica incluir un docstring que describa el propósito general del paquete. Ejemplo:
"""
Paquete: operaciones_matematicas
Este paquete incluye módulos para realizar cálculos matemáticos básicos y avanzados.
"""
Buenas Prácticas para Paquetes
- Organización y estructura:
- Diseñar paquetes con una jerarquía lógica y responsabilidades claras.
- Mantener los módulos pequeños y evitar dependencias circulares.
- Crear una estructura ordenada que facilite la navegación.
- Nombrado:
- Usar nombres significativos, cortos y en minúsculas para módulos y paquetes.
- Evitar nombres que puedan chocar con módulos estándar de Python.
- Uso del archivo
__init__.py
:- Documentar el propósito del paquete en un docstring.
- Simplificar importaciones exportando funciones clave en
__init__.py
. - Controlar lo que se expone con la variable
__all__
.
- Importaciones:
- Usar rutas relativas dentro del paquete para mejorar la portabilidad.
- Evitar from paquete import * para mantener claridad y evitar conflictos de nombres.
- Documentación:
- Documentar cada módulo, función y clase con docstrings claros.
- Incluir un archivo
README.md
. que explique el propósito del paquete y cómo usarlo.
- Pruebas:
- Agregar pruebas unitarias para cada módulo y usar herramientas como
pytest
. - Mantener las pruebas en un directorio separado dentro del proyecto.
- Agregar pruebas unitarias para cada módulo y usar herramientas como
- Distribución:
- Preparar un archivo
setup.py
para definir cómo se instala el paquete. - Documentar las dependencias y asegurarse de que el paquete cumpla estándares si se publicará en PyPI.
- Preparar un archivo
- Estilo y calidad:
- Seguir las normas de PEP 8 para escribir código limpio y legible.
- Usar herramientas como
flake8
oblack
para mantener la calidad del código. - Comentar adecuadamente partes complejas del código.
Primer Módulo
Módulo
Un módulo es simplemente un archivo con extensión .py
que contiene código Python, como funciones, variables o clases. Los módulos ayudan a dividir el código en partes reutilizables y organizadas.
Manejo de Módulos
-
module.py
: Archivo que contiene el código del módulo.print("Me gusta ser un módulo.")
-
main.py
: En este archivo se importa el módulomodule.py
, ambos archivos deben estar en la misma carpeta.import module
- Ejecutar
main.py
: se debe ver el mensaje "Me gusta ser un módulo". - Carpeta
__pycache__
: Al ejecutar el archivomain.py
se crea una carpeta con el nombre__pycache__
, el cual contiene el archivomodule.cpython-xy.pyc
: - Archivo
module.cpython-xy.pyc
:- El archivo se puede llamar (más o menos)
module.cpython-xy.pyc
dondex
yy
son dígitos derivados de la versión de Python (por ejemplo, serán 3 y 8 si s utiliza Python 3.8). - El nombre del archivo es el mismo que el del módulo. La parte posterior al primer punto dice qué implementación de Python ha creado el archivo (CPython) y su número de versión. La ultima parte (pyc) viene de las palabras Python y compilado.
- Cuando Python importa un módulo por primera vez, traduce el contenido a una forma algo compilada.
- El archivo no contiene código en lenguaje máquina: es código semi-compilado interno de Python, listo para ser ejecutado por el intérprete de Python. Como tal archivo no requiere tantas comprobaciones como las de un archivo fuente, la ejecución comienza más rápido y también se ejecuta más rápido.
- Gracias a eso, cada vez que se importe este archivo posteriormente será más rápida que interpretar el código fuente desde cero.
- Python puede verificar si el archivo fuente del módulo ha sido modificado (en este caso, el archivo pyc será reconstruido) o no (cuando el archivo pyc pueda ser ejecutado al instante). Este proceso es completamente automático y transparente, no tiene que ser tomando en cuenta.
- El archivo se puede llamar (más o menos)
- Ejecutar
module.py
: se debe ver el mensaje "Me gusta ser un módulo" otra vez. - Como se puede ver no hay ninguna diferencia en el resultado de la ejecución del código directamente desde el módulo
module.py
o desde un scriptmain.py
, para poder diferenciar quien ejecutó el código se usa la variable__name__
. - variable
__name__
: En Python, la variable especial__name__
es una cadena que se utiliza para determinar si un archivo Python está siendo ejecutado directamente o importado como un módulo. Esto es especialmente útil para controlar qué partes del código se ejecutan dependiendo del contexto.
Contextos de Uso de __name__
- Cuando un archivo se ejecuta directamente: Si se ejecuta directamente, Python asigna a
__name__
el valor__main__
. Esto permite identificar que el archivo es el programa principal. - Cuando un archivo se importa como módulo: Si el archivo es importado en otro archivo, Python asigna a
__name__
el nombre del archivo sin la extensión .py. Esto asegura que el bloque protegido con if__name__
==__main__
: no se ejecute.
Si al archivomodule.py
se le adiciona la instrucciónprint(__name__)
como se muestra a continuación:# module.py print("Me gusta ser un módulo.") print(__name__) # Salida: __main__
Al ejecutar este módulo la variable
__name__
toma el valor de__main__
.Si ejecuta el script que trabaja como paquete,
main.py
, la variable__name__
toma el valor demodule
es decir el nombre del archivo o módulo que se está importando sin la extensión.py
.# main.py import module # Salida: module
Sucede lo mismo con todos los módulos importados en el archivo
main.py
.
Buenas Prácticas para Módulos
- Usar nombres descriptivos y en minúsculas:
- El nombre del módulo debe reflejar claramente su propósito.
- Evitar nombres genéricos como utilidades.py o funciones.py.
- Ejemplo: calculos_financieros.py es más descriptivo que calculos.py.
- Evitar el uso de nombres de módulos conflictivos:No nombrar módulos con nombres que coincidan con bibliotecas estándar de Python (por ejemplo, math.py o json.py).
- Agrupar funciones relacionadas: Un módulo debe contener funciones, clases o variables que tengan un propósito común. Esto mejora la coherencia y facilita el mantenimiento.
- Evitar demasiadas responsabilidades en un módulo: Si un módulo crece demasiado, divídalo en varios módulos más pequeños.
- Documentar el módulo con un docstring: Incluir un resumen breve al principio del archivo que describa su propósito y cómo se usa.
- Controlar lo que se exporta: Utilizar la variable
__all__
para definir qué funciones, variables o clases estarán disponibles al usarfrom modulo import *
.# Exportar únicamente lo necesario __all__ = ['suma', 'promedio']
Plantilla Ejemplo
Se muestra un código nuevo del archivo module.py
. El módulo actualizado está aquí:
#!/usr/bin/env python3
"" module.py - an example of a Python module ""
__counter = 0
def suml(the_list):
global __counter
__counter += 1
the_sum = 0
for element in the_list:
the_sum += element
return the_sum
def prodl(the_list):
global __counter
__counter += 1
prod = 1
for element in the_list:
prod *= element
return prod
if __name__ == "__main__":
print("Prefiero ser un módulo, pero puedo hacer algunas pruebas para usted.")
my_list = [i+1 for i in range(5)]
print(suml(my_list) == 15)
print(prodl(my_list) == 120)
La línea que comienza con #!
recibe múltiples nombres, como shabang, shebang, hashbang, poundbang o incluso hashpling. Desde la perspectiva de Python, esta línea no es más que un comentario, ya que comienza con el carácter #
. Sin embargo, para los sistemas operativos basados en Unix y similares (incluido macOS), esta línea instruye al sistema operativo sobre cómo ejecutar el contenido del archivo, especificando qué programa debe interpretar el texto. En ciertos entornos, especialmente en aquellos relacionados con servidores web, la ausencia de esta línea puede ocasionar problemas de funcionamiento.
Por otro lado, una cadena de texto (que puede ser multilínea) ubicada antes de cualquier instrucción dentro de un módulo, incluidas las declaraciones de importación, se denomina doc-string. Su propósito es proporcionar una breve descripción del objetivo y contenido del módulo.
Las funciones definidas en el módulo, como suml()
y prodl()
, están disponibles para ser importadas y utilizadas en otros archivos.
Python no ofrece mecanismos para restringir el acceso a variables privadas de manera que solo puedan ser utilizadas dentro del módulo al que pertenecen. Se puede comunicar a los usuarios que esta variable es de uso exclusivo para lectura y que no debe ser modificada bajo ninguna circunstancia. Para indicar esta restricción, se antepone un guion bajo _
o dos guiones bajos __
al nombre de la variable. Sin embargo, es importante destacar que esta práctica es únicamente un acuerdo implícito y no una regla obligatoria, por lo que los usuarios del módulo pueden decidir si respetan esta convención o no.
Adicionalmente, la variable especial __name__
se utiliza para identificar si el archivo se está ejecutando de forma independiente. En tal caso, se aprovecha esta característica para realizar pruebas simples del código.
Primer Paquete
¿Qué Es un Paquete en Python?
Un paquete es una carpeta que:
- Contiene un archivo especial llamado
__init__.py
(en versiones modernas de Python, este archivo puede ser opcional). - Agrupa varios módulos relacionados.
- Puede contener subpaquetes, organizando el código en niveles jerárquicos.
mi_paquete/
__init__.py
modulo1.py
modulo2.py
subpaquete/
__init__.py
modulo3.py
En esta estructura:
mi_paquete
es el paquete principal.-
subpaquete
es un subpaquete dentro demi_paquete
. -
modulo1.py
,modulo2.py
, ymodulo3.py
son módulos que contienen funciones, clases o variables.
Crear un Paquete
- Crear un directorio: Este será el nombre del paquete.
- Añadir un archivo
mi_paquete/__init__.py
: Este archivo puede estar vacío o contener código para inicializar el paquete (por ejemplo, importar módulos por defecto).
Ejemplo:mi_paquete/__init__.py
puede contener:from .modulo1 import funcion1 from .modulo2 import clase2
- Añadir módulos al paquete: Crea archivos
.py
dentro de la carpeta del paquete.
Ejemplo demodulo1.py
:def funcion1(): print("Hola desde modulo1!")
Importar y Usar un Paquete
Una vez que el paquete está configurado, puede ser usado como un módulo normal en Python.
Ejemplo:
- Crear la siguiente estructura:
mi_paquete/ __init__.py modulo1.py modulo2.py
- Código en
modulo1.py
:def funcion1(): return "Función en modulo1"
- Código en modulo2.py:
def funcion2(): return "Función en modulo2"
- Importar en un script Python:
from mi_paquete import modulo1, modulo2 print(modulo1.funcion1()) # Salida: Función en modulo1 print(modulo2.funcion2()) # Salida: Función en modulo2
Paquetes con Subpaquetes
Si se tienen subpaquetes, se pueden organizar importaciones jerárquicas.
Ejemplo de estructura:
mi_paquete/
__init__.py
modulo1.py
subpaquete/
__init__.py
modulo3.py
Para usar el subpaquete:
from mi_paquete.subpaquete import modulo3
# Llamar funciones o clases de modulo3
resultado = modulo3.funcion3()
print(resultado)
Instalar y Usar Paquetes Externos
Python usa pip para instalar paquetes externos desde el índice PyPI.
- Instalar un paquete:
pip install numpy
- Usar el paquete instalado:
import numpy as np array = np.array([1, 2, 3]) print(array)
Buenas Prácticas
- Usa nombres descriptivos para paquetes y módulos.
- Evita conflictos de nombres (no uses nombres como
os.py
osys.py
). - Estructura el proyecto en paquetes para mantener el código organizado.
- Documenta los
__init__.py
para que otros sepan qué módulos contiene el paquete.
Diferencias entre Módulos y Paquetes
Aspecto | Módulo | Paquete |
---|---|---|
Definición | Un módulo es un archivo .py que contiene código Python reutilizable, como funciones, clases y variables. | Un paquete es un directorio que contiene módulos y subpaquetes, junto con un archivo especial __init__.py . |
Propósito | Permite dividir el código en partes pequeñas y reutilizables para mantener la organización. | Agrupa y organiza varios módulos relacionados en un nivel jerárquico, ideal para proyectos grandes. |
Estructura | Es un solo archivo Python. | Es una carpeta con módulos y un archivo __init__.py . |
Ejemplo | Archivo calculos.py con funciones matemáticas. | Carpeta matematicas/ que contiene módulos como calculos.py, estadisticas.py, y __init__.py . |
Importación | Se importa directamente usando import modulo . | Se importa como un conjunto jerárquico, por ejemplo, from paquete.modulo import función . |
Nivel de complejidad | Más simple, ideal para proyectos pequeños o funcionalidades específicas. | Más complejo, diseñado para proyectos más grandes o estructuras modulares avanzadas. |
Cuándo Usar Módulos y Paquetes
- Módulos: Úselos para scripts o funcionalidades independientes, cuando el proyecto es pequeño y no requiere organización compleja.
- Paquetes: Son útiles para proyectos grandes que requieren organización jerárquica y agrupación de funcionalidades relacionadas.