Web Server con Python

Python trae un servidor web en la biblioteca estándar. Sirve para dos cosas: compartir una carpeta en un segundo y entender cómo funciona HTTP por dentro. Para una web de verdad, no.

Servir una carpeta: una línea

python -m http.server 8000 --directory web
salida200 <p>archivo estático</p>

Abre http://localhost:8000 y verás el contenido de la carpeta web: el index.html si lo hay, o la lista de archivos si no. Es la forma más rápida de probar una página estática o de pasar un archivo a otro ordenador de tu red. Para cortarlo, Ctrl+C.

Por omisión escucha en todas las interfaces, así que lo ve cualquiera de tu red. Si solo lo quieres para ti, añade --bind 127.0.0.1.

Un manejador propio

from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler
import json

class Manejador(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == "/":
            cuerpo = "<h1>Hola desde Python</h1>".encode("utf-8")
            tipo = "text/html; charset=utf-8"
        elif self.path == "/api/hora":
            from datetime import datetime
            cuerpo = json.dumps({"hora": datetime.now().isoformat(timespec="seconds")}).encode()
            tipo = "application/json"
        else:
            self.send_error(404, "No existe")
            return

        self.send_response(200)
        self.send_header("Content-Type", tipo)
        self.send_header("Content-Length", str(len(cuerpo)))
        self.end_headers()
        self.wfile.write(cuerpo)

ThreadingHTTPServer(("127.0.0.1", 8000), Manejador).serve_forever()
tres peticiones/ 200 text/html; charset=utf-8 <h1>Hola desde Python</h1>
/api/hora 200 application/json {"hora": "2026-10-08T22:58:41"}
/nada 404 No existe

Un método do_GET que mira la ruta y decide. El orden de las llamadas es el del propio protocolo: primero el código de estado, después las cabeceras, una línea en blanco —que es lo que pone end_headers— y el cuerpo. El cuerpo tiene que ir en bytes, de ahí el encode, y el charset=utf-8 de la cabecera es lo que hace que el navegador muestre bien las tildes.

ThreadingHTTPServer atiende cada petición en su propio hilo, así que una petición lenta no bloquea a las demás. La versión anterior de esta página lo construía a mano combinando ThreadingMixIn con HTTPServer; desde Python 3.7 viene hecho.

http.server no es para producción, y lo dice la propia documentación de Python: no tiene más que comprobaciones de seguridad básicas. Para algo que vaya a estar expuesto a internet, un marco como Flask o FastAPI, detrás de un servidor de verdad. Lo de esta página sirve para aprender y para herramientas de uso interno.

Más información en inglés: Create a web server with Python.

Todo el código se ejecutó con Python 3.14 en un contenedor limpio antes de publicar esta página; las salidas están copiadas de esa ejecución.