Cómo hospedar una app o script de Python

Para hospedar una app de Python necesitas un servidor con la versión correcta de Python, tus dependencias instaladas y un comando de inicio. El puerto y los secretos vienen de variables de entorno.

Actualizado el 6 min de lectura

Objetivos de aprendizaje

Después de leer este artículo podrás:

  • Preparar un proyecto de Python para correr fuera de tu máquina
  • Escribir un script y una API que lean la configuración del entorno y se cierren bien
  • Verificar el deploy y corregir los errores más comunes
En esta página

Una app de Python funciona en tu máquina porque ahí están la versión correcta de Python, las librerías instaladas y las variables que configuraste. Hospedar es reproducir ese entorno en un servidor que se mantiene encendido todo el tiempo.

Hay dos casos comunes. Un script hace trabajo sin recibir visitas: un bot, un recolector de datos, una tarea programada. Una API escucha en un puerto y responde peticiones. El camino es el mismo para ambos, con una diferencia: solo la API necesita un puerto. Para la visión general, mira qué es el deploy.

1Proyecto localmain.pyrequirements.txt.gitignoreSubida al servidorsin .venv ni .env2Dependencias en un venvpip install -rrequirements.txt3Proceso de Python0.0.0.0 en el puerto de PORT4os.environvariables de entorno
Sube el código y el requirements.txt, recrea el venv en el servidor e inicia Python leyendo la configuración del entorno.

¿Qué necesitas antes de hospedar?#

  • Una versión de Python definida. Usa la misma en local y en producción.
  • Un requirements.txt con las dependencias y sus versiones.
  • Un archivo principal (aquí, main.py) que inicie todo.
  • Un lugar donde correr: VPS, contenedor o plataforma de hosting. La diferencia está en VPS vs plataforma en la nube.

¿Qué versión? Para un proyecto nuevo, prefiere una versión de Python en fase de corrección de bugs (bugfix), siempre que todas tus dependencias ya publiquen paquetes para ella. Las versiones más antiguas pasan a recibir solo correcciones de seguridad y después llegan al fin de su vida. El calendario oficial muestra la fase de cada versión.

¿Cómo preparas el proyecto con un venv?#

Un venv es un entorno aislado solo para este proyecto, que evita que las librerías de una app choquen con las de otra.

bash
mkdir mi-app && cd mi-app
python -m venv .venv
source .venv/bin/activate        # Windows (PowerShell): .venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install fastapi uvicorn
python -m pip freeze > requirements.txt

pip freeze guarda las versiones instaladas en requirements.txt. En el servidor, python -m pip install -r requirements.txt recrea el mismo entorno. Por eso la carpeta .venv no se sube: guarda rutas absolutas y no es portable. Agrega .venv/ y .env al .gitignore.

¿Cómo escribes un script que corre sin parar?#

Un script de larga duración tiene que leer la configuración del entorno, sobrevivir a un error aislado y detenerse bien cuando el servidor lo pida. Ese pedido llega con la señal SIGTERM, en reinicios y deploys.

python
import os
import signal
import sys
import time
import urllib.request

stopping = False


def handle_stop(signum, frame):
    global stopping
    stopping = True


signal.signal(signal.SIGTERM, handle_stop)
signal.signal(signal.SIGINT, handle_stop)

API_URL = os.environ.get("API_URL")
if not API_URL:
    sys.exit("API_URL no está definida")
INTERVAL = int(os.environ.get("INTERVAL_SECONDS", "60"))


def job():
    with urllib.request.urlopen(API_URL, timeout=10) as response:
        print(f"status {response.status}", flush=True)


while not stopping:
    try:
        job()
    except Exception as exc:  # un error aislado no tumba el proceso
        print(f"la tarea falló: {exc}", flush=True)
    for _ in range(INTERVAL):  # duerme de a 1 segundo para notar el SIGTERM pronto
        if stopping:
            break
        time.sleep(1)

print("cerrando", flush=True)

Qué hace cada parte:

  • os.environ: la URL y el intervalo vienen del entorno, no del código. Si falta API_URL, el script falla de inmediato con un mensaje claro.
  • stopping: el handler solo cambia una variable, y quien termina es el bucle principal. La espera se hace en pasos de 1 segundo, así que el script nota el SIGTERM en un segundo como máximo, aunque el intervalo sea largo.
  • flush=True: cuando la salida no es una terminal, Python guarda el print en un búfer y los logs llegan tarde. Ejecutar con python -u o definir PYTHONUNBUFFERED=1 tiene el mismo efecto.

Prueba en local con API_URL=https://example.com python main.py. Para tareas que corren en horarios fijos, mira qué es un cron job.

¿Cómo hospedas una API de Python?#

Una API necesita un servidor ASGI. El más usado con FastAPI es Uvicorn. La app mínima:

python
from fastapi import FastAPI

app = FastAPI()


@app.get("/health")
def health():
    return {"status": "ok"}

Inícialo con:

bash
uvicorn main:app --host 0.0.0.0 --port "${PORT:-8000}"

Dos detalles importan en producción. Primero, --host 0.0.0.0: por defecto solo escucha en 127.0.0.1, y desde fuera del contenedor o de la máquina nadie llega a la app. Segundo, el puerto sale de la variable PORT cuando la plataforma la define, con 8000 como valor de desarrollo.

Para comparar los frameworks, mira cómo hospedar FastAPI, Flask y Django. Lo que conviene revisar antes de abrirla al público está en el checklist de API en producción.

¿Cómo manejas las variables de entorno y los secretos?#

Los tokens, contraseñas de base de datos y claves de API viven en variables de entorno, nunca en el repositorio. En local, usa un archivo .env fuera de Git y exporta las variables antes de ejecutar, o usa python-dotenv. En producción, define cada una en el panel de tu proveedor. El patrón completo está en qué son las variables de entorno.

¿Cómo verificas que funcionó?#

  1. Logs: deben mostrar el inicio del script o Uvicorn escuchando, sin traceback después.
  2. Petición: llama a /health en la dirección pública y espera {"status":"ok"}.
  3. Reinicio: reinicia la app y confirma que vuelve sola y que SIGTERM imprime la línea "cerrando".

¿Cuáles son los errores más comunes?#

  • ModuleNotFoundError: No module named 'fastapi': la dependencia no se instaló o no está en requirements.txt. Ejecuta pip freeze de nuevo con el venv activo.
  • Error al instalar o compilar un paquete: la versión de Python del servidor es distinta de la local y la librería aún no tiene paquete listo para ella. Alinea las versiones.
  • La app arranca pero el sitio no abre: el servidor escucha en 127.0.0.1 o en un puerto fijo. Usa 0.0.0.0 y el puerto del entorno.
  • Logs vacíos o con retraso: búfer de salida. Usa flush=True o PYTHONUNBUFFERED=1.
  • Funciona en local, falla en producción: falta una variable de entorno o hay poca memoria. Compara ambos entornos. Si es memoria, mira cómo dimensionar RAM y CPU.
  • El script muere y no vuelve: nada lo reinicia. Usa un servidor o contenedor con política de reinicio. Para empaquetarlo, mira cómo dockerizar una app.

Cómo hacerlo en Square Cloud#

Los dos casos de esta guía se convierten en dos tipos de aplicación en Square Cloud. Subes el proyecto como ZIP en el panel, con la CLI, desde GitHub (un push dispara el deploy) o con la extensión de VS Code, y al iniciar la plataforma ejecuta pip install -r requirements.txt, el mismo archivo que generaste en el venv. La salida de la instalación aparece en los logs, así que un ModuleNotFoundError te dice enseguida qué paquete faltó. El archivo squarecloud.app es opcional: el panel lo genera en el deploy.

El script corre como aplicación en segundo plano, sin subdominio: el formulario de deploy detecta main.py, y el proceso usa desde 256 MB de la RAM del plan, sin recibir tráfico entrante. La API es una aplicación web, con al menos 512 MB y un subdominio *.squareweb.app con HTTPS. Como un main.py con FastAPI solo define app, completa el comando de inicio con uvicorn main:app --host 0.0.0.0 --port $PORT; la plataforma define la variable PORT.

API_URL e INTERVAL_SECONDS se cargan como variables de entorno de la aplicación en el panel, que también importa un .env; ya existen durante la instalación y valen desde el siguiente reinicio. El contenedor está siempre encendido, y el reinicio automático, activado por defecto en el deploy desde el panel, levanta el proceso cuando termina con error. Quedarse sin memoria, en cambio, detiene la aplicación hasta que aumentes su RAM. Mantén flush=True o PYTHONUNBUFFERED=1 para ver cada línea en los logs en tiempo real.

La RAM del plan es un pool compartido: en el Hobby, que empieza en R$12,49 al mes con 1 GB, un script con 256 MB y una API con 512 MB caben juntos. Python es uno de varios runtimes, junto a Node.js, Go y Java: consulta los runtimes disponibles hoy en Runtimes y los detalles del runtime de Python.

Hosting de APIs

APIs en contenedores siempre encendidos, sin cold start

Más información

Preguntas frecuentes

¿Qué versión de Python usar en producción?

Usa una versión de Python en fase de corrección de bugs (bugfix) que tus librerías acepten. El calendario oficial de Python muestra la fase de cada versión; revísalo antes de fijar la versión en tu proyecto.

¿Debo subir la carpeta del venv junto con el código?

No. El venv guarda rutas absolutas y depende del sistema operativo. Sube el código y el requirements.txt, y deja que el servidor recree el entorno con pip install -r requirements.txt.

¿Cómo mantengo un script de Python corriendo 24/7?

Pon el script en un bucle que espere entre ejecuciones y córrelo en un servidor o contenedor que reinicie el proceso si falla. Si depende de tu computadora, se detiene cuando la apagas.

¿Necesito un servidor web para hospedar un script?

No. Un script que solo ejecuta tareas, como un bot o un recolector de datos, no necesita abrir un puerto. Solo las APIs y los sitios deben escuchar en uno.

Siguiente artículoQué es un cron job y cómo programar tareasUn cron job es una tarea que corre sola en horarios definidos por una expresión de 5 campos. Mira sintaxis, ejemplos, errores comunes y cómo programar en Node.js.