Python desde cero, parte 2: módulos, POO, APIs, entornos virtuales y proyectos reales
Segunda parte de la guía de Python desde cero. Aprende módulos, paquetes, entornos virtuales, programación orientada a objetos, manejo de JSON, APIs, testing básico, organización de proyectos, buenas prácticas y mini proyectos más reales.

Python desde cero, parte 2: pasar de scripts simples a proyectos reales
La primera parte de esta guía cubrió los fundamentos esenciales: variables, condiciones, bucles, listas, diccionarios, funciones, errores, archivos y proyectos pequeños. Esta segunda parte continúa desde ahí. El objetivo ya no es solo escribir fragmentos de código que funcionen, sino aprender a organizar programas, reutilizar lógica, trabajar con datos externos, consumir APIs, crear estructuras más limpias y preparar proyectos que puedan crecer sin volverse caóticos.
Python se vuelve mucho más poderoso cuando entiendes cómo dividir tu código en módulos, cómo instalar dependencias sin romper tu sistema, cómo representar entidades con clases, cómo leer y escribir JSON, cómo hacer pruebas básicas y cómo mantener una estructura de carpetas razonable. Estos temas suelen aparecer justo después de los fundamentos, cuando el principiante empieza a preguntarse: “¿cómo convierto esto en algo más serio?”
Antes de empezar
Esta es la Parte 2. Si aún no dominas variables, condiciones, bucles, funciones, listas, diccionarios, errores y archivos, empieza por la Parte 1.
1. Módulos: dividir el código para no repetirlo
Cuando un programa es pequeño, puedes escribir todo en un solo archivo. Pero esa estrategia deja de funcionar cuando el código crece. Un módulo en Python es simplemente un archivo .py que contiene funciones, variables o clases reutilizables. Separar el código en módulos permite ordenar responsabilidades: un archivo para cálculos, otro para lectura de datos, otro para validaciones y otro para ejecutar el programa principal.
La idea central es que cada archivo tenga un propósito claro. Si tienes funciones para calcular impuestos, no necesitan vivir en el mismo archivo donde preguntas datos al usuario. Si tienes validaciones de contraseña, pueden estar en un módulo aparte. Esto hace que el programa sea más fácil de leer, probar y modificar.
# archivo: operaciones.py
def sumar(a, b):
return a + b
def restar(a, b):
return a - b
# archivo: main.py
from operaciones import sumar, restar
print(sumar(10, 5))
print(restar(10, 5))Regla práctica
Cuando un archivo empieza a mezclar demasiadas responsabilidades, probablemente necesita dividirse en módulos más pequeños.
2. Paquetes y estructura básica de proyecto
Un paquete es una carpeta que agrupa módulos relacionados. En proyectos modernos de Python, una estructura clara ayuda a separar código fuente, pruebas, documentación y archivos de configuración. Aunque seas principiante, aprender una estructura mínima evita malos hábitos desde temprano.
No necesitas crear arquitecturas enormes. Una estructura simple basta: una carpeta src para el código principal, una carpeta tests para pruebas, un archivo README.md para explicar el proyecto y un archivo requirements.txt para registrar dependencias. Esta organización hace que cualquier persona pueda entender qué hace el proyecto, cómo ejecutarlo y qué librerías necesita.
mi_proyecto/
README.md
requirements.txt
src/
main.py
utilidades.py
tests/
test_utilidades.py| Elemento | Para qué sirve | Cuándo usarlo |
|---|---|---|
| src/ | Contener el código principal del proyecto. | Siempre que el proyecto tenga más de un archivo. |
| tests/ | Guardar pruebas automáticas. | Cuando quieras verificar funciones sin hacerlo manualmente. |
| README.md | Explicar instalación, uso y propósito. | En todo proyecto que quieras compartir o mantener. |
| requirements.txt | Registrar dependencias externas. | Cuando instales librerías con pip. |
3. Entornos virtuales: no mezcles dependencias
Un entorno virtual es una carpeta aislada donde Python instala librerías para un proyecto específico. Sin entornos virtuales, puedes terminar con dependencias mezcladas: un proyecto necesita una versión de una librería, otro proyecto necesita otra, y tu instalación global se vuelve difícil de controlar.
La herramienta venv viene incluida con Python y es suficiente para empezar. La idea es simple: creas un entorno, lo activas, instalas dependencias dentro de él y guardas esas dependencias en requirements.txt. Así otra persona puede reproducir tu entorno con más facilidad.
python -m venv .venv
# macOS / Linux
source .venv/bin/activate
# Windows PowerShell
.venv\Scripts\Activate.ps1
pip install requests
pip freeze > requirements.txtNo subas .venv a tus repositorios
El entorno virtual puede pesar mucho y depende de tu máquina. Lo normal es subir requirements.txt, no la carpeta .venv completa.
4. Programación orientada a objetos: clases sin misterio
La programación orientada a objetos, o POO, suele intimidar a quienes empiezan. Pero la idea inicial es sencilla: una clase sirve para describir un tipo de cosa, y un objeto es una instancia concreta de esa cosa. Por ejemplo, puedes tener una clase Tarea y crear varias tareas con título, estado y prioridad.
No uses clases por obligación. Para scripts pequeños, funciones y diccionarios pueden bastar. Las clases se vuelven útiles cuando tienes datos y comportamientos que pertenecen juntos. Una tarea no solo tiene un título; también puede marcarse como completada. Un producto no solo tiene precio; también puede calcular descuento. Ahí las clases empiezan a aportar orden.
class Tarea:
def __init__(self, titulo, prioridad):
self.titulo = titulo
self.prioridad = prioridad
self.completada = False
def completar(self):
self.completada = True
def resumen(self):
estado = "completada" if self.completada else "pendiente"
return f"{self.titulo} ({self.prioridad}) - {estado}"
tarea = Tarea("Practicar Python", "alta")
print(tarea.resumen())
tarea.completar()
print(tarea.resumen())Cuándo no usar clases
Si una función simple resuelve el problema con claridad, no necesitas crear una clase. La POO debe reducir complejidad, no decorarla.
5. JSON: el formato que conecta aplicaciones
JSON es uno de los formatos más usados para intercambiar datos entre aplicaciones. Se parece mucho a los diccionarios y listas de Python: claves, valores, arreglos y objetos anidados. Por eso es una excelente siguiente parada después de aprender diccionarios.
Puedes usar JSON para guardar configuraciones, exportar datos, leer respuestas de APIs o construir archivos que otras aplicaciones puedan consumir. Python incluye el módulo json, así que no necesitas instalar nada para empezar.
import json
usuario = {
"nombre": "Ana",
"lenguaje": "Python",
"nivel": "principiante"
}
with open("usuario.json", "w", encoding="utf-8") as archivo:
json.dump(usuario, archivo, indent=2, ensure_ascii=False)
with open("usuario.json", "r", encoding="utf-8") as archivo:
datos = json.load(archivo)
print(datos["nombre"])
print(datos["lenguaje"])6. APIs: pedir datos a otros servicios
Una API permite que un programa hable con otro. Cuando una aplicación consulta el clima, obtiene precios, valida direcciones o muestra información de una plataforma externa, probablemente está consumiendo una API. Para aprender, lo importante no es memorizar todos los detalles de HTTP, sino entender el flujo: haces una petición, recibes una respuesta, revisas si fue exitosa y procesas los datos.
La librería requests simplifica mucho ese trabajo. No viene incluida por defecto, así que conviene instalarla dentro de un entorno virtual. En proyectos reales, también debes manejar errores: la API puede no responder, el servidor puede devolver un código inesperado o los datos pueden venir incompletos.
import requests
url = "https://api.github.com/repos/python/cpython"
respuesta = requests.get(url, timeout=10)
if respuesta.status_code == 200:
datos = respuesta.json()
print("Repositorio:", datos["full_name"])
print("Estrellas:", datos["stargazers_count"])
else:
print("Error al consultar la API:", respuesta.status_code)Se usa para pedir información. Por ejemplo: consultar un usuario, producto, clima o repositorio.
7. Testing básico: comprobar que tus funciones siguen funcionando
Probar manualmente cada función una y otra vez funciona al principio, pero se vuelve lento y poco confiable. El testing básico permite escribir pequeñas verificaciones automáticas. Si cambias una función y algo se rompe, una prueba puede avisarte antes de que el error llegue a producción o a un usuario.
Python incluye unittest, aunque muchas personas también usan pytest. Para empezar, basta con entender una idea: una prueba llama a una función con valores conocidos y verifica que el resultado sea el esperado. Esto te obliga además a escribir funciones más pequeñas y claras.
# archivo: calculos.py
def aplicar_descuento(precio, porcentaje):
return precio - (precio * porcentaje)
# archivo: test_calculos.py
import unittest
from calculos import aplicar_descuento
class TestCalculos(unittest.TestCase):
def test_aplicar_descuento(self):
self.assertEqual(aplicar_descuento(100, 0.10), 90)
if __name__ == "__main__":
unittest.main()8. Depuración: aprender a leer errores sin miedo
Depurar no significa adivinar. Significa observar el comportamiento del programa, encontrar dónde deja de hacer lo esperado y corregir la causa. Para principiantes, el primer paso es aprender a leer el traceback: Python normalmente indica el archivo, la línea y el tipo de error.
También puedes usar print estratégicos para revisar valores, aunque con el tiempo conviene aprender el depurador del editor. La clave es no cambiar diez cosas al mismo tiempo. Cambia una, ejecuta, observa y repite. Así construyes criterio.
| Error frecuente | Qué suele significar | Cómo investigarlo |
|---|---|---|
| NameError | Usaste una variable o función que no existe. | Revisa nombres, mayúsculas y orden de definición. |
| TypeError | Intentaste operar tipos incompatibles. | Imprime el tipo con type(valor). |
| KeyError | Buscaste una clave inexistente en un diccionario. | Revisa las claves disponibles con .keys(). |
| IndexError | Intentaste acceder a una posición que no existe en una lista. | Comprueba len(lista) antes de acceder. |
Un buen programador no es quien nunca ve errores; es quien aprende a convertir cada error en una pista útil.
Mini proyecto: agenda de contactos en JSON
Este proyecto une varios temas nuevos: funciones, listas de diccionarios, JSON, lectura y escritura de archivos. La idea es crear una agenda mínima que guarda contactos en un archivo contactos.json. No tiene interfaz gráfica ni base de datos, pero ya se comporta como una herramienta persistente: los datos no desaparecen al cerrar el programa.
Este tipo de proyecto es ideal para practicar porque puede crecer poco a poco. Primero guardas contactos. Luego agregas búsqueda. Después validas correos. Más adelante puedes convertirlo en una API o en una aplicación web.
import json
ARCHIVO = "contactos.json"
def cargar_contactos():
try:
with open(ARCHIVO, "r", encoding="utf-8") as archivo:
return json.load(archivo)
except FileNotFoundError:
return []
def guardar_contactos(contactos):
with open(ARCHIVO, "w", encoding="utf-8") as archivo:
json.dump(contactos, archivo, indent=2, ensure_ascii=False)
def agregar_contacto(nombre, email):
contactos = cargar_contactos()
contactos.append({"nombre": nombre, "email": email})
guardar_contactos(contactos)
agregar_contacto("Ana", "ana@example.com")
print(cargar_contactos())Guardar contactos
Crear funciones para cargar, guardar y agregar contactos en JSON.
Buscar contactos
Agregar una función para buscar por nombre o correo.
Validar datos
Evitar correos vacíos, nombres repetidos o contactos incompletos.
Menú por consola
Crear opciones para listar, agregar, buscar y salir.
Buenas prácticas que empiezan a importar ahora
En la Parte 1, la prioridad era entender los fundamentos. En esta Parte 2, la claridad del proyecto empieza a importar más. Un programa puede funcionar y aun así ser difícil de mantener. Por eso conviene adoptar buenas prácticas desde temprano: nombres descriptivos, funciones pequeñas, comentarios útiles, estructura de carpetas simple y control de dependencias.
No confundas buenas prácticas con rigidez. El objetivo no es escribir código perfecto, sino evitar caos innecesario. Un principiante que aprende a organizar proyectos desde temprano avanza más rápido cuando llega a web, datos, automatización o backend.
Código claro
Prefiere nombres como calcular_total, cargar_contactos o validar_email antes que abreviaturas ambiguas.
Comentarios útiles
Comenta el porqué de una decisión, no cada línea obvia. El código debe explicar el qué.
Conclusión: ya no estás solo escribiendo código, estás diseñando proyectos
La Parte 2 marca un cambio importante. Ya no se trata únicamente de entender instrucciones básicas, sino de empezar a pensar como alguien que diseña programas mantenibles. Módulos, paquetes, entornos virtuales, clases, JSON, APIs y pruebas son piezas que aparecen constantemente en proyectos reales.
No necesitas dominarlas todas de inmediato. El camino correcto es construir algo pequeño, mejorarlo, romperlo, depurarlo y volverlo a organizar. Cuando puedas crear una agenda en JSON, consumir una API, escribir una prueba y dividir tu código en módulos, estarás mucho más preparado para entrar en desarrollo web, automatización profesional, análisis de datos o backend.
Rigor Core
¿Quieres construir algo parecido?
Si este artículo conecta con el tipo de plataforma, sistema o producto que quieres lanzar, puedes hablarnos de tu caso y lo aterrizamos contigo.
