Entorno de ejecución de Python

El tiempo de ejecución de Python es la pila de software responsable de instalar el código de tu aplicación y sus dependencias, y, a continuación, ejecutar esa aplicación en el entorno flexible.

Versiones de Python

Python 3.13 usa buildpacks. Para ver la lista completa de versiones de Python admitidas y sus correspondientes versiones de Ubuntu, consulta el calendario de asistencia de tiempo de ejecución.

Para usar una versión de Python compatible, debes hacer lo siguiente:

  • Incluye los ajustes runtime_config y operating_system en el archivo app.yaml para especificar un sistema operativo.

  • Instala la versión 420.0.0 o posterior de la CLI de gcloud. Puedes actualizar tus herramientas de CLI ejecutando el comando gcloud components update. Para ver la versión instalada, ejecuta el comando gcloud version.

  • También puedes especificar una versión del tiempo de ejecución incluyendo el ajuste runtime_version en el archivo app.yaml. De forma predeterminada, se usa la versión más reciente de Python si no se especifica el ajuste runtime_version.

Ejemplos

  • Para especificar Python 3.13 en Ubuntu 22, haz lo siguiente:

    runtime: python
    env: flex
    entrypoint: gunicorn -b :$PORT main:app
    
    runtime_config:
        operating_system: "ubuntu22"
        runtime_version: "3.13"
    
  • Para especificar la versión de Python más reciente compatible en Ubuntu 22, haz lo siguiente:

      runtime: python
      env: flex
      entrypoint: gunicorn -b :$PORT main:app
    
      runtime_config:
          operating_system: "ubuntu22"
    

Consulta la página de referencia de app.yaml para obtener más información.

Versiones anteriores del entorno de ejecución

En Python versión 3.7 y anteriores, se especifica una versión mediante los ajustes runtime_config y python_version en el archivo app.yaml de la aplicación.

Ejemplo

runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app

runtime_config:
    python_version: 3.7

En las versiones de Python 3.7 y anteriores, el intérprete predeterminado es Python 2.7.12 si se omiten runtime_config o python_version. Por ejemplo, puedes usar el tiempo de ejecución predeterminado especificando runtime: python en el archivo app.yaml:

runtime: python
env: flex

Consulta la página de referencia de app.yaml para obtener más información.

En la siguiente tabla se muestran los intérpretes que se implementan para cada ajuste de versión:

python_version ajuste Intérprete implementado ID de entorno de ejecución Ejemplo: app.yaml
2 (predeterminado) 2.7.12 python2 runtime_config:
python_version: 2
3.4 3.4.8 python34 runtime_config:
python_version: 3.4
3.5 3.5.9 python35 runtime_config:
python_version: 3.5
3 o 3.6 3.6.10 python36 runtime_config:
python_version: 3
3.7 3.7.9 python37 runtime_config:
python_version: 3.7

Compatibilidad con otros entornos de ejecución de Python

Si necesitas usar una versión de Python que no sea compatible, puedes crear un entorno de ejecución personalizado y seleccionar una imagen base válida con la versión de Python que necesites.

Para obtener información sobre las imágenes base proporcionadas por Google o las imágenes base de Python de Docker, consulta el artículo Crear tiempos de ejecución personalizados.

Para obtener más información sobre cómo contenerizar aplicaciones de App Engine para Cloud Run, consulta la guía de migración.

Dependencias

El tiempo de ejecución busca un archivo requirements.txt en el directorio de origen de tu aplicación y usa pip para instalar las dependencias antes de iniciar la aplicación. Para obtener más información sobre cómo declarar y gestionar paquetes, consulta el artículo Usar bibliotecas de Python.

Si tu aplicación requiere dependencias privadas, debes usar un tiempo de ejecución personalizado basado en el tiempo de ejecución de Python para instalar los paquetes adecuados.

Inicio de la aplicación

El tiempo de ejecución inicia tu aplicación con el entrypoint definido en el archivo app.yaml. El punto de entrada debe iniciar un proceso que responda a las solicitudes HTTP en el puerto definido por la variable de entorno PORT.

La mayoría de las aplicaciones web usan un servidor WSGI, como Gunicorn, uWSGI o Waitress.

Para poder usar uno de estos servidores, debes añadirlo como dependencia en el archivo requirements.txt de tu aplicación. Si usas gunicorn en tu aplicación Flask, asegúrate de que la versión de Python de tu aplicación sea compatible con gunicorn.

El tiempo de ejecución se asegura de que todas las dependencias estén instaladas antes de que se llame a tu punto de entrada.

Flask==2.0.2
gunicorn==20.1.0

Ejemplo de punto de entrada que usa gunicorn para una aplicación Flask:

entrypoint: gunicorn -b :$PORT main:app

Un ejemplo de punto de entrada que usa Gunicorn para una aplicación Django:

entrypoint: gunicorn -b :$PORT mydjangoapp:wsgi

Gunicorn es el servidor WSGI recomendado, pero puedes usar cualquier otro servidor WSGI. Por ejemplo, aquí tienes un punto de entrada que usa uWSGI con Flask:

entrypoint: uwsgi --http :$PORT --wsgi-file main.py --callable app

En el caso de las aplicaciones que pueden gestionar solicitudes sin un servidor WSGI, solo tienes que ejecutar una secuencia de comandos de Python:

entrypoint: python main.py

Los ejemplos de puntos de entrada básicos que se muestran arriba son puntos de partida y pueden funcionar en sus aplicaciones web. Sin embargo, la mayoría de las aplicaciones necesitarán configurar el servidor WSGI. En lugar de especificar todos los ajustes en el punto de entrada, crea un archivo gunicorn.conf.py en el directorio raíz de tu proyecto, donde se encuentra el archivo app.yaml, y especifícalo en el punto de entrada:

entrypoint: gunicorn -c gunicorn.conf.py -b :$PORT main:app

Puedes consultar todos los valores de configuración de Gunicorn en su documentación.

Trabajadores

Gunicorn usa workers para gestionar las solicitudes. De forma predeterminada, Gunicorn usa trabajadores síncronos. Esta clase de trabajador es compatible con todas las aplicaciones web, pero cada trabajador solo puede gestionar una solicitud a la vez. De forma predeterminada, gunicorn solo usa uno de estos trabajadores. Esto puede provocar que tus instancias estén infrautilizadas y aumentar la latencia en las aplicaciones con mucha carga.

Te recomendamos que definas el número de trabajadores como entre 2 y 4 veces el número de núcleos de CPU de tu instancia más uno. Puedes especificarlo en gunicorn.conf.py de la siguiente forma:

import multiprocessing

workers = multiprocessing.cpu_count() * 2 + 1

Además, algunas aplicaciones web que están principalmente limitadas por las operaciones de entrada/salida pueden experimentar una mejora del rendimiento si usan una clase de trabajador diferente. Si tu clase de trabajador requiere dependencias adicionales, como gevent o tornado, esas dependencias deberán declararse en el archivo requirements.txt de tu aplicación.

Proxies HTTPS y de reenvío

App Engine finaliza la conexión HTTPS en el balanceador de carga y reenvía la solicitud a tu aplicación. La mayoría de las aplicaciones no necesitan saber si la solicitud se ha enviado a través de HTTPS o no, pero las aplicaciones que sí necesitan esta información deben configurar Gunicorn para que confíe en el proxy de App Engine de la siguiente manera:gunicorn.conf.py

forwarded_allow_ips = '*'
secure_scheme_headers = {'X-FORWARDED-PROTO': 'https'}

Gunicorn ahora se asegurará de que el wsgi.url_scheme a 'https', que la mayoría de los frameworks web usarán como indicación de que la solicitud es segura. Si tu servidor o framework WSGI no admite esta opción, comprueba el valor del encabezado X-Forwarded-Proto manualmente.

Algunas aplicaciones también necesitan determinar la dirección IP del usuario. Esta opción está disponible en el encabezado X-Forwarded-For.

Ten en cuenta que el ajuste secure_scheme_headers de gunicorn.conf.py debe estar en mayúsculas, como X-FORWARDED-PROTO, pero los encabezados que puede leer tu código estarán en una combinación de mayúsculas y minúsculas, como X-Forwarded-Proto.

Prolongar el tiempo de ejecución

El tiempo de ejecución de Python del entorno flexible se puede usar para crear un tiempo de ejecución personalizado. Para obtener más información, consulta Personalizar Python.

Variables de entorno

El entorno de ejecución define las siguientes variables de entorno:

Variable de entorno Descripción
GAE_INSTANCE Nombre de la instancia actual.
GAE_MEMORY_MB Cantidad de memoria disponible para el proceso de la aplicación.
GAE_SERVICE El nombre del servicio especificado en el archivo app.yaml de tu aplicación o, si no se ha especificado ningún nombre de servicio, se define como default.
GAE_VERSION Etiqueta de versión de la aplicación actual.
GOOGLE_CLOUD_PROJECT El ID del proyecto asociado a tu aplicación, que se puede ver en la Google Cloud consola
PORT Puerto que recibirá las solicitudes HTTP.

Puedes definir variables de entorno adicionales en el archivo app.yaml.

Servidor de metadatos

Cada instancia de tu aplicación puede usar el servidor de metadatos de Compute Engine para consultar información sobre la instancia, como su nombre de host, su dirección IP externa, su ID de instancia, sus metadatos personalizados y la información de su cuenta de servicio. App Engine no te permite definir metadatos personalizados para cada instancia, pero puedes definir metadatos personalizados de todo el proyecto y leerlos desde tus instancias de App Engine y Compute Engine.

Esta función de ejemplo usa el servidor de metadatos para obtener la dirección IP externa de la instancia:

METADATA_NETWORK_INTERFACE_URL = (
    "http://metadata/computeMetadata/v1/instance/network-interfaces/0/"
    "access-configs/0/external-ip"
)


def get_external_ip():
    """Gets the instance's external IP address from the Compute Engine metadata
    server.

    If the metadata server is unavailable, it assumes that the application is running locally.

    Returns:
        The instance's external IP address, or the string 'localhost' if the IP address
        is not available.
    """
    try:
        r = requests.get(
            METADATA_NETWORK_INTERFACE_URL,
            headers={"Metadata-Flavor": "Google"},
            timeout=2,
        )
        return r.text
    except requests.RequestException:
        logging.info("Metadata server could not be reached, assuming local.")
        return "localhost"