← Todos los recursos

Python · Operación de APIs · RECURSO GRATUITO

Mi API responde en local, pero fuera falla

Tres diagnósticos completos: conexión rechazada, ruta incorrecta y proceso vivo sin datos preparados. Evidencias, pistas y soluciones; sin cuenta ni tarjeta.

30–60 minutos orientativos. Puedes parar y repetir a tu ritmo.

HTML independiente, imprimible como PDF. Sin registro.

Qué necesitas: Para diagnosticar basta un navegador con JavaScript; ordenador recomendado. Para repetir de verdad: Python 3.12+, dos terminales y una carpeta nueva. El servidor gratuito es docente y solo escucha en 127.0.0.1; no publicarlo en Internet.

Investiga tres fallos de una API

Laboratorio de diagnóstico. Tres casos preparados, sin ejecutar servicios o acceder a tu equipo. No exige cuenta, Docker ni tarjeta para diagnosticar. Después puedes repetirlos con Python real en local.

Preparando el diagnóstico…

Guardar en mi cuenta envía solo tus respuestas, notas y caso seleccionado. No guarda evidencias consultadas ni comprobaciones; no hay guardado automático. Sin cuenta puedes practicar y descargar tus respuestas. No escribas secretos ni datos personales. Puedes exportar o borrar estos guardados con las herramientas de privacidad de WordPress.

Qué necesitas: Para diagnosticar basta un navegador con JavaScript; ordenador recomendado. Para repetir de verdad: Python 3.12+, dos terminales y una carpeta nueva. El servidor gratuito es docente y solo escucha en 127.0.0.1; no publicarlo en Internet.

Tu resultado: Distinguir fallo de conexión, respuesta 404 y readiness 503, justificando causa, cambio y comprobación.

Repite con Python real en tu equipo

Guarda el siguiente código como gratis.py en una carpeta nueva. En una terminal ejecuta python gratis.py servir. Mantén esa terminal abierta. En otra ejecuta las peticiones siguientes. No necesitas comprar el curso ni instalar Docker. Esta alternativa es local; no ejecuta Gunicorn o TLS y no sustituye el laboratorio del curso.

"""Práctica gratuita local. Servidor docente, nunca publicar en Internet."""

from contextlib import closing
import argparse
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import json
from pathlib import Path
import sqlite3
import urllib.request
import urllib.error


def handler(db):
    class Handler(BaseHTTPRequestHandler):
        def log_message(self, *args):
            pass

        def do_GET(self):
            code, data = 404, {"error": "ruta"}
            if self.path == "/healthz":
                code, data = 200, {"vivo": True}
            if self.path == "/readyz":
                try:
                    with closing(
                        sqlite3.connect(
                            Path(db).resolve().as_uri() + "?mode=ro",
                            uri=True,
                        )
                    ) as c:
                        c.execute("SELECT valor FROM comprobacion").fetchone()
                    code, data = 200, {"lista": True}
                except sqlite3.Error:
                    code, data = 503, {"lista": False}
            body = json.dumps(data).encode()
            self.send_response(code)
            self.send_header("Content-Type", "application/json")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)

    return Handler


if __name__ == "__main__":
    p = argparse.ArgumentParser(description=__doc__)
    p.add_argument("accion", choices=["iniciar", "servir", "consultar"])
    p.add_argument("--db", default="gratis.sqlite")
    p.add_argument("--puerto", type=int, default=18991)
    p.add_argument("--ruta", default="/healthz")
    a = p.parse_args()
    if a.accion == "iniciar":
        if Path(a.db).exists():
            raise SystemExit(
                "La base ya existe; usa otro nombre para repetir sin sobrescribir"
            )
        with closing(sqlite3.connect(a.db)) as c, c:
            c.execute("CREATE TABLE comprobacion(valor TEXT)")
            c.execute("INSERT INTO comprobacion VALUES('datos ficticios')")
        print("Base local preparada")
    elif a.accion == "servir":
        print("Solo local: http://127.0.0.1:" + str(a.puerto), flush=True)
        ThreadingHTTPServer(("127.0.0.1", a.puerto), handler(a.db)).serve_forever()
    else:
        if not a.ruta.startswith("/") or a.ruta.startswith("//"):
            raise SystemExit("Ruta inválida")
        try:
            try:
                r = urllib.request.urlopen(
                    "http://127.0.0.1:" + str(a.puerto) + a.ruta, timeout=3
                )
            except urllib.error.HTTPError as e:
                r = e
            with r:
                print(r.status, r.read().decode())
        except urllib.error.URLError:
            raise SystemExit(
                "Conexión rechazada: revisa proceso y puerto; no es un 404 HTTP"
            )
Necesito una pista

En Windows puedes usar py -3.12 en lugar de python. En macOS/Linux utiliza python3 si corresponde.

Ver solución de este reto
Detén el servidor con Ctrl+C. Para repetir usa otra carpeta o un nombre de base nuevo; iniciar nunca sobrescribe una base existente.

Un fallo de conexión no tiene estado HTTP;404 y 503 son respuestas de un servidor que sí ha atendido la petición.

Comprueba: Explica cada resultado antes de consultar la solución.

Comandos y resultados observables

Caso1: con servir activo en 18991, consulta primero 18992: debe fallar la conexión. Corrige al 18991:200. Caso2: /health devuelve 404 y /healthz 200. Caso3: /readyz 503 antes de iniciar; después 200 sin reiniciar el proceso. Usa una carpeta nueva para garantizar que no había base previa. Comprueba que 18992 no lo usa otro servicio: recibir un HTTP allí no es conexión rechazada. Si está ocupado, elige otro puerto sin un servidor propio y no detengas procesos ajenos.

python gratis.py servir
# En otra terminal:
python gratis.py consultar --puerto 18992
python gratis.py consultar --puerto 18991

python gratis.py consultar --ruta /health
python gratis.py consultar --ruta /healthz

python gratis.py consultar --ruta /readyz
python gratis.py iniciar
python gratis.py consultar --ruta /readyz
Necesito una pista

No borres datos de otros proyectos para repetir. Un archivo de base distinto permite otro ensayo.

Ver solución de este reto
Conexión rechazada → puerto.404 → ruta.503 en readyz con healthz 200 → dependencia de datos no preparada.

Cada cambio corrige una frontera y se confirma repitiendo la petición que fallaba.

Comprueba: Usa --db otra.sqlite tanto en servir como en iniciar para repetir con una base independiente. Los nombres con espacios, # o % también funcionan; escríbelos entre comillas.

Tu turno

Cambia el puerto del servidor y del cliente de forma coherente; repite los tres resultados y explica qué has aprendido sin copiar las soluciones.

Ver solución y explicación
Predice → observa → cambia una causa → repite la misma petición → explica el estado posterior.

No hay un servidor dentro del playground. Las evidencias son preparadas. Comprobar no avanza ni concede XP; guardar respuestas/notas en cuenta es manual. La guía contiene todo el código gratuito para practicar sin cuenta.

Explícalo con tus palabras

  • ¿La conexión rechazada es un 404?
  • ¿Un 200 de healthz prueba que la base está lista?
  • ¿Qué resultado confirma tu corrección?

Repite con datos distintos antes de marcarlo como practicado. Esta es una autoevaluación, no una certificación.

Guarda tu siguiente paso

Todo el recurso es gratuito y puedes descargarlo sin cuenta. Si te registras, podrás guardar esta práctica y retomarla desde Mi cuenta.

Entrar y guardar Crear cuenta gratis

Crear una cuenta no te suscribe a correos promocionales.