Python 執行階段

Python 執行階段是軟體堆疊,負責安裝應用程式程式碼和依附元件,然後在彈性環境中執行該應用程式。

Python 版本

Python 3.15 (預先發布版) 使用 buildpack。如需支援的 Python 版本完整清單,以及對應的 Ubuntu 版本,請參閱「執行階段支援時間表」。

如要使用支援的 Python 版本,請務必:

  • 在 app.yaml 檔案中加入 runtime_config 和 operating_system 設定,指定作業系統。

  • 安裝 gcloud CLI 420.0.0 以上版本。您可以執行 gcloud components update 指令,更新 CLI 工具。如要查看已安裝的版本,請執行 gcloud version 指令。

  • 您也可以在 app.yaml 檔案中加入 runtime_version 設定,指定執行階段版本。根據預設,如果未指定 runtime_version 設定,系統會使用最新的 Python 版本。

範例

  • 如要在 Ubuntu 24 指定 Python 3.15 (預先發布版):

    runtime: python
    env: flex
    entrypoint: gunicorn -b :$PORT main:app
    
    runtime_config:
        operating_system: "ubuntu24"
        runtime_version: "3.15"
    
  • 如要在 Ubuntu 24 指定支援的最新 Python 版本,請執行下列指令:

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

詳情請參閱 app.yaml 參考資料頁面。

支援其他 Python 執行階段

如需使用不支援的 Python 版本,可以建立自訂執行階段,並選取具有所需 Python 版本的有效基礎映像檔。

如要瞭解 Google 提供的基本映像檔或 Docker Python 基本映像檔,請參閱「建構自訂執行階段」。

如要進一步瞭解如何將 App Engine 應用程式容器化,以便在 Cloud Run 中執行,請參閱遷移指南。

依附元件

執行階段會在應用程式的來源目錄中尋找 requirements.txt 檔案,並使用 pip 安裝任何依附元件,然後才啟動應用程式。如要進一步瞭解如何宣告及管理套件,請參閱「使用 Python 程式庫」。

如果應用程式需要私人依附元件,您必須使用以 Python 執行階段為基礎的自訂執行階段,才能安裝適當的套件。

啟動應用程式

執行階段會使用 app.yaml 檔案中定義的 entrypoint 啟動應用程式。進入點應啟動程序,在環境變數 PORT 定義的通訊埠上回應 HTTP 要求。

大多數網頁應用程式會使用 WSGI 伺服器,例如 Gunicorn、uWSGI 或 Waitress。

您必須先在應用程式的 requirements.txt 中將這些伺服器新增為依附元件,才能使用。如果您在 Flask 應用程式中使用 gunicorn,請確認應用程式的 Python 版本與 gunicorn 相容。

執行階段會確保所有依附元件都已安裝,再呼叫進入點。

Flask==2.0.2
gunicorn==20.1.0

以下為使用 gunicorn 的 Flask 應用程式進入點範例:

entrypoint: gunicorn -b :$PORT main:app

以下為使用 gunicorn 的 Django 應用程式進入點範例:

entrypoint: gunicorn -b :$PORT mydjangoapp:wsgi

建議使用的 WSGI 伺服器為 gunicorn,不過若您想要使用任何其他的 WSGI 伺服器也絕對不成問題。例如,以下就是一個使用 uWSGI 的 Flask 應用程式進入點:

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

如果應用程式不需 WSGI 伺服器即可處理要求,您只要執行 Python 指令碼即可:

entrypoint: python main.py

上方所示的進入點基本範例皆可做為起點,並可直接用於您的網路應用程式。然而,大多數的應用程式都需要進一步設定 WSGI 伺服器。請在專案根目錄 (app.yaml 檔案所在位置) 建立 gunicorn.conf.py 檔案,並在進入點指定該檔案,而不是在進入點指定所有設定:

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

如果想要瞭解 Gunicorn 的所有設定值,請參閱其說明文件。

工作站

Gunicorn 使用工作站來處理要求。根據預設,Gunicorn 會使用 sync 工作站。這個類別的工作站與所有網路應用程式相容,但每個工作站一次只能處理一個要求。在預設情況下,Gunicorn 只會使用當中的一個工作站來處理要求。這通常會導致執行個體使用率過低,並使高負載應用程式的延遲情況加重。

我們建議將工作站的數量設為執行個體 CPU 核心數量的 2 至 4 倍再加 1。您可以在 gunicorn.conf.py 中指定,如下所示:

import multiprocessing

workers = multiprocessing.cpu_count() * 2 + 1

此外,某些主要受限於 I/O 的網頁應用程式,在使用不同的 worker 類別後,效能可能會有所提升。如果 worker 類別需要額外的依附元件 (例如 gevent 或 tornado),則必須在應用程式的 requirements.txt 中宣告這些依附元件。

HTTPS 和轉送 Proxy

App Engine 會在負載平衡器上終止 HTTPS 連線,並將要求轉送至您的應用程式。大多數應用程式不需要知道要求是否透過 HTTPS 傳送,但需要這項資訊的應用程式應設定 Gunicorn,在 gunicorn.conf.py 中信任 App Engine Proxy:

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

Gunicorn 現在會確保 wsgi.url_scheme 設為 'https',大多數網頁架構都會將其視為要求安全的指標。如果 WSGI 伺服器或架構不支援這項功能,請手動檢查 X-Forwarded-Proto 標頭的值。

有些應用程式還需確認使用者的 IP 位址,這項資訊會顯示在 X-Forwarded-For 標頭中。

請注意,gunicorn.conf.py 中的 secure_scheme_headers 設定應為大寫,例如 X-FORWARDED-PROTO,但程式碼可讀取的標頭會是大小寫混合,例如 X-Forwarded-Proto。

擴充執行階段

彈性環境 Python 執行階段可用於建立自訂執行階段。詳情請參閱「自訂 Python」。

環境變數

執行階段環境會設定下列環境變數:

環境變數 說明
GAE_INSTANCE 目前執行個體的名稱。
GAE_MEMORY_MB 應用程式程序可用的記憶體量。
GAE_SERVICE 應用程式的 app.yaml 檔案中指定的服務名稱;如果未指定服務名稱,則設為 default。
GAE_VERSION 目前應用程式的版本標籤。
GOOGLE_CLOUD_PROJECT 與應用程式相關聯的專案 ID,可在 Google Cloud 控制台查看
PORT 接收 HTTP 要求的通訊埠。

您可以在 app.yaml 檔案中設定其他環境變數。

中繼資料伺服器

您應用程式中的每個執行個體都可以使用 Compute Engine 中繼資料伺服器來查詢該執行個體的相關資訊,包括主機名稱、外部 IP 位址、執行個體 ID、自訂中繼資料,以及服務帳戶資訊。App Engine 不允許您為每個執行個體設定自訂中繼資料,但您可以設定專案層級的自訂中繼資料,並從 App Engine 和 Compute Engine 執行個體讀取。

這個函式範例使用中繼資料伺服器,以取得執行個體的外部 IP 位址:

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"