Lección 44 de 45 · Proyectos y cierre

Proyecto: consumir una API

Una API deja de parecer magia cuando separas cuatro cosas: pedir, recibir, comprobar y transformar. Practicaremos ese flujo sin depender de Internet.

Paso a pasoDiagnóstico por capasAvanza a tu ritmo
Índice · Lección 44/45
Proyecto 3 · primero entiende el viaje de los datos

Consumir una API real añade red, librerías, claves y servicios externos. Para aprender sin ruido, simularemos las respuestas y nos centraremos en la parte que sí debes dominar: qué haces con una respuesta cuando llega.

Evidencia de aprendizaje

Diagnosticar si un fallo pertenece a red, estado HTTP, forma de datos o lógica de la aplicación.

Piensa en la API como un mostrador con un contrato

Tu programa hace una petición y el servicio devuelve una respuesta. Esa respuesta suele contener, como mínimo, un estado que indica cómo fue la operación y un cuerpo con datos o información del error.

Una respuesta simulada
respuesta = {
    "status": 200,
    "json": {"nombre": "Ada", "lenguaje": "Python"},
}

print(respuesta["status"])
print(respuesta["json"]["nombre"])

No importa que una librería real use objetos y métodos distintos. El modelo mental permanece: primero sabes si la operación fue bien y después interpretas qué datos recibiste.

Comprueba el estado antes de tocar los datos

Un error habitual es ir directamente a respuesta["json"]["nombre"]. Si el servicio ha devuelto un error, quizá esa estructura ni siquiera exista.

La primera bifurcación
respuesta = {"status": 404, "json": {"mensaje": "No encontrado"}}

if respuesta["status"] == 200:
    print(respuesta["json"]["nombre"])
else:
    print("No se pudieron obtener los datos")

Esta comprobación convierte un fallo externo en una ruta prevista del programa. No estás “ocultando” el error: estás decidiendo qué experiencia tendrá la persona que usa tu aplicación.

Los datos externos no tienen por qué respetar tus suposiciones

Incluso con un estado correcto puede faltar una clave. Antes de mezclar la respuesta con el resto de tu programa, conviene transformarla a una forma interna sencilla y controlada.

Extrae solo lo que tu programa necesita
def extraer_perfil(datos):
    return {
        "nombre": datos.get("nombre", "Sin nombre"),
        "repos": datos.get("repos", 0),
    }

print(extraer_perfil({"nombre": "Ada"}))

Ahora el resto de la aplicación ya no necesita conocer todos los detalles de la respuesta externa. Trabaja con dos campos que tú has decidido y con valores por defecto explícitos.

Un fallo de red, un 404 y un JSON incompleto son problemas distintos

  • No llega respuesta: piensa en conexión, timeout o servicio caído.
  • Llega un estado de error: la comunicación funcionó, pero la petición no produjo el recurso esperado.
  • El cuerpo no tiene la forma prevista: revisa el contrato de datos y valida campos.
  • Los datos son válidos pero tu resultado es incorrecto: el problema ya está en tu lógica.

Nombrar bien la capa reduce muchísimo la frustración. En lugar de “la API no funciona”, puedes decir “recibo estado 200, pero falta la clave repos”. Esa frase ya contiene una pista útil.

Prueba tres capas de respuesta sin depender de Internet

Red¿llegó respuesta?
Estado¿200 o error?
Datos¿tiene la forma esperada?
Lógica¿la transformo correctamente?

Completa la función para manejar tres casos: éxito, estado de error y JSON válido pero sin nombre.

Salida esperada
Ada
No disponible
Sin nombre
api_simulada.py
La salida aparecerá aquí.

Necesito una pista
  • Primero decide según status.
  • Solo en el caso 200 accede al JSON. Para el nombre usa .get("nombre", "Sin nombre").
Ver una solución razonada
def nombre_o_mensaje(respuesta):
    if respuesta["status"] == 200:
        return respuesta["json"].get("nombre", "Sin nombre")
    return "No disponible"

ok = {"status": 200, "json": {"nombre": "Ada"}}
error = {"status": 503, "json": {"mensaje": "Servicio no disponible"}}
incompleta = {"status": 200, "json": {}}

print(nombre_o_mensaje(ok))
print(nombre_o_mensaje(error))
print(nombre_o_mensaje(incompleta))
Puente opcional: una petición HTTP real en Python local

Cuando quieras conectar Internet, conserva exactamente el mismo modelo y añade un timeout. Este ejemplo está pensado para Python local; el navegador puede aplicar restricciones de red como CORS.

import json
from urllib.request import urlopen
from urllib.error import URLError

url = "https://jsonplaceholder.typicode.com/users/1"

try:
    with urlopen(url, timeout=5) as respuesta:
        datos = json.load(respuesta)
        print(datos.get("name", "Sin nombre"))
except URLError as error:
    print("Fallo de red:", error)

Cuando conectes una API real, mantén exactamente estas capas

En una integración real, una librería o la biblioteca estándar realizará la petición HTTP. Añadirás una URL, quizá parámetros, autenticación y un tiempo máximo de espera. No cambies el modelo mental: la función que habla con la red debería entregar una respuesta que otra parte pueda validar y transformar.

Regla útil: nunca diseñes un proyecto de aprendizaje que solo funciona cuando Internet, el servidor y una clave externa están perfectos. Mantén respuestas de ejemplo para poder probar tu lógica sin depender del servicio.

Proyecto completado cuando…

puedes explicar el recorrido petición → respuesta → estado → datos → transformación y decir en qué paso investigarías cada tipo de fallo.