Módulos y Paquetes en Python



@eduardo_gpg

Número de visitas 3735

Tiempo de lectura 4 min

28 Diciembre 2020

Sin duda alguna, en algún momento de nuestra carrera, los proyectos en los que estemos trabajando comenzarán a crecer, a tal punto, que será necesario comenzar a modularizar nuestro código, delegando responsabilidades a nuevas funciones, métodos, clases y archivos.

Es por ello que, esta ocasión, me gustaría hablar acerca de módulos y paquetes en Python. Temas que sin duda nos ayudarán a organizar, de mejor manera, nuestro código, volviéndolo mucho más fácil de leer, probar, y por supuesto, de mantener.

Es sumamente interesante, así que te invito a que te quedes.

Bien, una vez dicho todo esto, y sin más por añadir, comencemos. 🧐

Módulos 🐛

Comencemos con la pregunta obligada ¿Qué es un módulo? Bueno, en términos simples un módulo no es más que un archivo, de texto plano, con extensión .py. Dentro del archivo almacenaremos código Python. Podremos crear variables, ciclos, condicionales, funciones, clases etc..

Aquí un ejemplo.

main.py

username = 'eduardo_gpg'
print('Hola' + useraname)

Siguiendo la guía de codificación PEP8, se nos recomienda que el nombre de nuestro módulos siga las siguientes convenciones. 🥳

  • Todos los caracteres deben encontrarse en minúsculas.
  • El nombre del módulo debe ser corto.
  • Si es necesario se podrá usar guión bajo (_) para mejorar la legibilidad del nombre.

En mi caso el módulo main.py cumple con todos los puntos. 😎

Lo interesante de los módulos es la capacidad de poder abstraer nuestro código y almacenarlo bajo diferentes contextos, en archivos diferentes.

Por ejemplo, si ahora tengo la necesidad de crear la clase User, y al ser esta una entidad completamente independiente, podemos crear un módulo solo para ella.

user.py

class User():
    def __init__(self, username, password):
        self.username = username
        self.password = password


    def __str__(self):
        return self.username

Perfecto. Ahora, si quisiera utilizar esta clase en el módulo main lo que debo hacer es simplemente importarla.

main.py

from user import User

eduardo = User('eduardo_gpg', 'password')
print(eduardo)

Como podemos observar, para el import basta con definir el nombre del módulo, no es necesario colocar su extensión.

De igual forma, es importante destacar que, si nosotros ejecutamos el script, una nueva carpeta se habrá creado en nuestro directorio. Esta carpeta tiene por nombre __pycache__. Dentro de la carpeta encontraremos archivos compilados con extensión pyc.

Sí, así como lo lees, archivos compilados.

Se que hemos escuchado innumerables veces que Python es un lenguaje interpretado, y hasta cierto punto lo es, sin embargo cuando se importa un módulo por primera vez, o cuando el módulo es modificado, Python genera un binario de ello. Esto lo hace con la finalidad de mejorar el performance en tiempo de ejecución. Recordemos que, computacionalmente hablando, es mucho más rápido ejecutar un binario que interpretar y ejecutar una archivo.

Por lo tanto, siempre que importemos módulos en Python, el interprete generará nuevos archivos .pyc dentro de la carpeta __pycache__.

Paquetes 🦝

Listo, ya hablamos sobre módulos, ahora toca el turno de hablar sobre paquetes. Así que respondamos a la pregunta ¿Qué es un paquete? En términos simples podemos decir que, un paquete no es más que un directorio (carpeta/folder) donde se almacenan diferentes módulos de Python, módulos agrupados bajo un mismo contexto.

Para que nos quede más en claro planteemos el siguiente escenario.

Nuestro proyecto sigue creciendo, y ahora es necesario crear 2 nuevos tipos de usuarios, clientes y vendedores. Al ser entidades con una relación (Ambas serán clases hijas de User) lo que debemos hacer será agrupar todos estos nuevos módulos en un nuevo paquete. 😲

En mi caso el paquete puede tener por nombre entities.

La estructura quedaría de la siguiente manera.

customer.py

from .user import User

class Customer (User):
    pass

seller.py

from .user import User

class Seller(User):
    pass

Directorio

root/

├── entities/
│   ├── __init__.py
│   ├── user.py
│   ├── seller.py
│   ├── customer.py

└── main.py

Aquí hay un par de cosas a resaltar. Primero, para que una carpeta/folder pueda considerarse como un paquete, obligatoriamente, debe almacenar el archivo __init__.py. Por ahora podemos dejar este archivo completamente vacío, con el simple hecho que este exista dentro de la carpeta será más que suficiente.

Segundo, como quizás te pudiste percatar, ahora, al los módulos encontrarse dentro de un paquete el import ha cambiado un poco. Hacemos uso de punto (.) para hacer referencia al paquete per se. 🤠

Ejemplo.

from .user import User

Con esta línea de indicamos a Python que queremos importar la clase User del módulo user que se encuentra dentro de este paquete.

De igual forma podemos ser más explícitos, de indicar directamente el nombre del paquete.

from entities.user import User

De ambas formas obtendríamos el mimo resultado. Aun que en lo personal he visto más el uso de punto (.). 😅

Listo, de esta forma habremos creado nuestro primer paquete en Python, pero ¿Cómo utilizarlo? bueno para ello debemos importar.

main.py

from entities.customer import Customer
from entities.seller import Seller

Ahora comenzamos con el nombre del paquete, punto (.) y módulo del cual queremos obtener un objeto. 🐍

Si ejecutamos, la carpeta __pycache__ junto con los archivos binarios serán creados dentro del paquete.

Archivo init.

Anteriormente mencionamos que, para que un carpeta/folder pueda ser considerada como paquete debe poseer el archivo __init__.py, pero ¿Exactamente para que sirve este archivo?

Bueno, hay que partir que, cuando se importa el paquete por primera vez, el primer y único archivo del paquete que se ejecuta es el archivo __init__.py, lo cual resulta de suma utilidad para poder instanciar todos aquellos objetos que el paquete necesite.

Podemos ver al archivo __init__.py como el paquete mismo. Todos los objetos que se creen dentro de este archivo podrán ser utilizados a través por el paquete.

Veamos un ejemplo.

__init__.py

ARTICLE = 'Módulos y paquetes en Python'

main.py

from entities import ARTICLE 

Observamos cómo, al crear la constante ARTICLE en el archivo __init__.py podemos acceder a ella utilizando únicamente el paquete from entities import ARTICLE

Con esto en mente, podemos hacer un refactor al archivo main.py

__init__.py

from .seller import Seller
from .customer import Customer

main.py

from entities import Seller
from entities import Customer

Ahora que las clases ya fueron expuestas por el paquete, ya no es necesario acceder a ellas a través de módulos.

Skol 🍻


¿El contenido te resulto de ayuda?

Para poder dejar tu opinión es necesario ser un usuario autenticado. Login

Más Tips y Ejercicios 🐍

Adquiere una subscripción PyWombat por tan solo $3 USD. al mes.

Conoce los beneficios de ser usuario premium:
Niveles desbloqueados: Ten accesos a todos los niveles de ejercicios. 🔓
Nuevo límite: Incrementa tu límite de ejercicios por semana. 🚀
Contenido único: Recibe semanalmente recursos exclusivos de Python (Videos, Artículos y Capitulos del libro PyWombat, comienza como desarrollador Python. 🐍