Il runtime di Python

Il runtime di Python è lo stack software responsabile dell'installazione del codice e delle dipendenze dell'applicazione, nonché dell'esecuzione dell'applicazione nell'ambiente flessibile.

Versioni di Python

Python 3.12 utilizza buildpack. Per l'elenco completo delle versioni di Python supportate e della relativa versione di Ubuntu, consulta la pianificazione del supporto del runtime.

Per utilizzare una versione di Python supportata, devi:

  • Includi le impostazioni runtime_config e operating_system nel app.yaml per specificare un sistema operativo.

  • Installa gcloud CLI versione 420.0.0 o successive. Puoi aggiornare gli strumenti CLI eseguendo il comando gcloud components update. Per visualizzare la versione installata, esegui il comando gcloud version.

  • Se vuoi, puoi specificare una versione di runtime includendo l'impostazione runtime_version nel file app.yaml. Per impostazione predefinita, viene utilizzata la versione Python più recente se l'impostazione runtime_version non è specificata.

Esempi

  • Per specificare Python 3.12 su Ubuntu 22:

    runtime: python
    env: flex
    entrypoint: gunicorn -b :$PORT main:app
    
    runtime_config:
        operating_system: "ubuntu22"
        runtime_version: "3.12"
    
  • Per specificare la versione Python più recente supportata su Ubuntu 22:

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

Per ulteriori informazioni, consulta la pagina di riferimento app.yaml.

Versioni precedenti dell'ambiente di runtime

Per Python versione 3.7 e precedenti, specifica una versione utilizzando le impostazioni runtime_config e python_version nel file app.yaml della tua applicazione.

Esempio

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

runtime_config:
    python_version: 3.7

Per le versioni di Python 3.7 e precedenti, l'interprete predefinito è Python 2.7.12 se runtime_config o python_version vengono omessi. Ad esempio, puoi utilizzare il runtime predefinito specificando runtime: python nel file app.yaml:

runtime: python
env: flex

Per ulteriori informazioni, consulta la pagina di riferimento app.yaml.

Gli interpreti di cui è stato eseguito il deployment per ogni impostazione della versione sono riportati nella tabella seguente:

python_version impostazione Interprete di cui è stato eseguito il deployment ID runtime Esempio di app.yaml
2 (valore predefinito) 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

Supporto di altri runtime Python

Se devi utilizzare una versione di Python non supportata, puoi creare un runtime personalizzato e selezionare un'immagine di base valida con la versione di Python di cui hai bisogno.

Per le immagini di base fornite da Google o per le immagini di base Docker Python, consulta Creare runtime personalizzati.

Per approfondire la contenimento delle app App Engine per Cloud Run, consulta la guida alla migrazione.

Dipendenze

Il runtime cerca un requirements.txt file nella directory di origine dell'applicazione e utilizza pip per installare eventuali dipendenze prima di avviare l'applicazione. Per ulteriori informazioni sulla dichiarazione e sulla gestione dei pacchetti, consulta Utilizzare le librerie Python.

Se la tua app richiede dipendenze private, devi utilizzare un runtime personalizzato basato sul runtime Python per installare i pacchetti appropriati.

Avvio dell'applicazione

Il runtime avvia l'applicazione utilizzando il file entrypoint definito nel file app.yaml. Il punto di contatto deve avviare un processo che risponda alle richieste HTTP sulla porta definita dalla variabile di ambiente PORT.

La maggior parte delle applicazioni web utilizza un server WSGI come Gunicorn, uWSGI o Waitress.

Prima di poter utilizzare uno di questi server, devi aggiungerlo come dipendenza nel requirements.txt dell'applicazione. Se utilizzi gunicorn per la tua applicazione Flask, assicurati che la versione di Python dell'applicazione sia compatibile con gunicorn.

Il runtime garantisce che tutte le dipendenze siano installate prima dell'esecuzione del punto di contatto.

Flask==2.0.2
gunicorn==20.1.0

Un punto di contatto di esempio che utilizza gunicorn per un'applicazione Flask:

entrypoint: gunicorn -b :$PORT main:app

Un punto di ingresso di esempio che utilizza gunicorn per un'applicazione Django:

entrypoint: gunicorn -b :$PORT mydjangoapp:wsgi

Gunicorn è il server WSGI consigliato, ma è possibile utilizzare qualsiasi altro server WSGI. Ad esempio, ecco un punto di contatto che utilizza uWSGI con Flask:

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

Per le applicazioni che possono gestire le richieste senza un server WSGI, puoi semplicemente eseguire uno script Python:

entrypoint: python main.py

Gli esempi di punto di contatto di base mostrati sopra sono pensati come punti di partenza e potrebbero funzionare per le tue applicazioni web. Tuttavia, per la maggior parte delle applicazioni sarà necessario configurare ulteriormente il server WSGI. Anziché specificare tutte le impostazioni nell'entry point, crea un file gunicorn.conf.py nella directory principale del progetto, dove si trova il file app.yaml, e specificalo nell'entry point:

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

Puoi trovare informazioni su tutti i valori di configurazione di Gunicorn nella relativa documentazione.

Worker

Gunicorn utilizza i worker per gestire le richieste. Per impostazione predefinita, Gunicorn utilizza i worker sincronizzati. Questa classe di worker è compatibile con tutte le applicazioni web, ma ogni worker può gestire una sola richiesta alla volta. Per impostazione predefinita, gunicorn utilizza solo uno di questi worker. Ciò può spesso causare un sottoutilizzo delle istanze e aumentare la latenza nelle applicazioni sottoposte a un carico elevato.

Ti consigliamo di impostare il numero di worker su 2-4 volte il numero di core della CPU dell'istanza più uno. Puoi specificarlo in gunicorn.conf.py come:

import multiprocessing

workers = multiprocessing.cpu_count() * 2 + 1

Inoltre, alcune applicazioni web che sono per lo più legate all'I/O possono registrare un miglioramento delle prestazioni utilizzando una classe di worker diversa. Se la classe di lavoro richiede dipendenze aggiuntive come gevent o tornado, queste dipendenze dovranno essere dichiarate nel file requirements.txt dell'applicazione.

Proxy HTTPS e di inoltro

App Engine termina la connessione HTTPS al bilanciatore del carico e inoltra la richiesta alla tua applicazione. La maggior parte delle applicazioni non ha bisogno di sapere se la richiesta è stata inviata tramite HTTPS o meno, ma le applicazioni che hanno bisogno di queste informazioni devono configurare Gunicorn in modo che attenda il proxy App Engine nel file gunicorn.conf.py:

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

Ora Gunicorn garantirà che wsgi.url_scheme e 'https', che la maggior parte dei framework web utilizzerà come indicazione della richiesta, siano sicuri. Se il tuo server o framework WSGI non lo supporta, controlla manualmente il valore dell'intestazione X-Forwarded-Proto.

Alcune applicazioni devono anche accertarsi dell'indirizzo IP dell'utente. Questa opzione è disponibile nell'intestazione X-Forwarded-For.

Tieni presente che l'impostazione secure_scheme_headers in gunicorn.conf.py deve essere in maiuscolo, come X-FORWARDED-PROTO, ma le intestazioni che il codice può leggere saranno in lettere maiuscole e minuscole, come X-Forwarded-Proto.

Estensione del runtime

Il runtime Python dell'ambiente flessibile può essere utilizzato per creare un runtime personalizzato. Per saperne di più, consulta Personalizzazione di Python.

Variabili di ambiente

Le seguenti variabili di ambiente vengono impostate dall'ambiente di runtime:

Variabile di ambiente Descrizione
GAE_INSTANCE Il nome dell'istanza corrente.
GAE_MEMORY_MB La quantità di memoria disponibile per la procedura di richiesta.
GAE_SERVICE Il nome del servizio specificato nel file app.yaml dell'applicazione oppure, se non è specificato alcun nome del servizio, viene impostato su default.
GAE_VERSION L'etichetta della versione dell'applicazione corrente.
GOOGLE_CLOUD_PROJECT L'ID progetto associato alla tua applicazione, visibile nella console Google Cloud
PORT La porta che riceverà le richieste HTTP.

Puoi impostare altre variabili di ambiente nel file app.yaml.

Server dei metadati

Ogni istanza della tua applicazione può utilizzare il server metadati di Compute Engine per eseguire query sulle informazioni sull' istanza, inclusi il nome host, l'indirizzo IP esterno, l'ID istanza, i metadati personalizzati e i dati dell'account di servizio. App Engine non ti consente di impostare metadati personalizzati per ogni istanza, ma puoi impostare metadati personalizzati a livello di progetto e leggerli dalle tue istanze App Engine e Compute Engine.

Questa funzione di esempio utilizza il server dei metadati per recuperare l'indirizzo IP esterno dell'istanza:

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"