Python 运行时

Python 运行时是负责安装应用代码和依赖项,然后在柔性环境中运行该应用的软件栈。

  • 3.8 版及更高版本是使用 buildpack 构建的,后者要求您在 app.yaml 文件中选择操作系统。例如,如需使用 Python 3.12,您必须将 Ubuntu 22 指定为操作系统。

  • 3.7 及更低版本使用 Docker 构建。

如需查看支持的 Python 版本及其对应的 Ubuntu 版本的完整列表,请参阅运行时支持时间表

新运行时版本

对于 Python 运行时 3.8 版及更高版本,您必须在 app.yaml 文件中添加 runtime_configoperating_system 设置以指定操作系统。

如需使用新版运行时,您必须安装 gcloud CLI 420.0.0 版或更高版本。您可以通过运行 gcloud components update 命令来更新 CLI 工具。如需查看已安装的版本,请运行 gcloud version 命令。

可选:您可以通过在 app.yaml 文件中添加 runtime_version 设置来指定运行时版本。默认情况下,如果未指定 runtime_version 设置,则使用最新的 Python 版本。

示例

  • 如需在 Ubuntu 22 上指定 Python 3.12,请执行以下操作:

    runtime: python
    env: flex
    entrypoint: gunicorn -b :$PORT main:app
    
    runtime_config:
        operating_system: "ubuntu22"
        runtime_version: "3.12"
    
  • 如需在 Ubuntu 22 上指定支持的最新 Python 版本,请执行以下操作:

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

如需了解详情,请参阅 app.yaml 参考页面。

过往运行时版本

对于 Python 3.7 版及更低版本,您可以在应用的 app.yaml 文件中使用 runtime_configpython_version 设置来指定版本。

示例

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

runtime_config:
    python_version: 3.7

对于 Python 3.7 版及更早版本,如果省略 runtime_configpython_version,则默认解释器为 Python 2.7.12。例如,您可以通过在 app.yaml 文件中指定 runtime: python 来使用默认运行时:

runtime: python
env: flex

如需了解详情,请参阅 app.yaml 参考页面。

为每个版本设置部署的解释器如下表所示:

python_version 设置 部署的解释器 运行时 ID app.yaml 示例
2(默认) 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
33.6 3.6.10 python36 runtime_config:
python_version: 3
3.7 3.7.9 python37 runtime_config:
python_version: 3.7

其他 Python 运行时支持

如果所需的 Python 版本未列出,则有以下几种选择:

  1. App Engine 柔性环境:创建自定义运行时,并选择包含您所需的 Python 版本的有效基础映像。
  2. App Engine 标准环境:支持 Python 3.7、3.8、3.9、3.10 和 3.11。
  3. Cloud Functions:支持 Python 3.7、3.8、3.9 和 3.10。
  4. Cloud Run:根据所需的 Python 版本的容器映像将应用容器化(请参阅其 Python 快速入门)。由于 Python 3.10 映像已经发布,因此您现在可以部署该版本。

对于 App Engine 柔性环境或 Cloud Run,请参阅 Google Cloud 提供的基础映像的构建自定义运行时,或当前可用的 Python 映像(包括 Python 2 映像信息)的Docker Python 基础映像

如需进一步了解适用于 Cloud Run 的 App Engine 应用容器化,请参阅介绍使用 Docker不使用 Docker 进行容器化的相关 Codelab 和视频内容。请注意,此内容目前仅涵盖 App Engine 标准环境到 Cloud Run 的迁移。

依赖项

在启动应用之前,运行时会在应用的源代码目录中查找 requirements.txt 文件,并使用 pip 安装所有依赖项。如需详细了解如何声明和管理软件包,请参阅使用 Python 库

如果您的应用需要专用依赖项,您将需要使用基于 Python 运行时的自定义运行时来安装相应的软件包。

搭配 Python 使用 C 库

为了支持使用需要 C 扩展程序的 Python 软件包,系统中预先安装了当前 Python 版本的头文件和以下 Ubuntu 软件包

  • build-essential
  • ca-certificates
  • curl
  • gfortran
  • git
  • libatlas-dev
  • libblas-dev
  • libcurl4-openssl-dev
  • libffi-dev
  • libfreetype6-dev
  • libjpeg-dev
  • liblapack-dev
  • libmemcached-dev
  • libmysqlclient-dev
  • libpng12-dev
  • libpq-dev
  • libquadmath0
  • libsasl2-2
  • libsasl2-dev
  • libsasl2-modules
  • libsqlite3-dev
  • libssl-dev
  • libxml2-dev
  • libxslt1-dev
  • libz-dev
  • mercurial
  • netbase
  • pkg-config
  • sasl2-bin
  • swig
  • wget
  • zlib1g-dev

这些软件包支持安装最热门的 Python 扩展程序。如果您的应用需要其他操作系统级依赖项,您将需要使用基于此运行时的自定义运行时来安装相应的软件包。

应用启动

运行时使用 app.yaml 文件中定义的 entrypoint 来启动应用。entrypoint 应启动一个进程,以响应环境变量 PORT 所定义端口上的 HTTP 请求。

大多数 Web 应用都使用 WSGI 服务器,例如 GunicornuWSGIWaitress

如需使用其中一个服务器,您必须将其作为依赖项添加到应用的 requirements.txt 文件中。 如果您将 gunicorn 用于 Flask 应用,请确保应用的 Python 版本与 gunicorn 兼容

运行时会确保所有依赖项均在 entrypoint 调用之前安装完毕。

Flask==2.0.2
gunicorn==20.1.0

在 Flask 应用中使用 gunicorn 时对应的 entrypoint 示例:

entrypoint: gunicorn -b :$PORT main:app

在 Django 应用中使用 gunicorn 时对应的 entrypoint 示例:

entrypoint: gunicorn -b :$PORT mydjangoapp:wsgi

建议您使用 Gunicorn 作为 WSGI 服务器,但您完全可以使用任何其他 WSGI 服务器。下面提供了一个将 uWSGI 与 Flask 搭配使用的 entrypoint 示例:

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

对于可以在没有 WSGI 服务器的情况下处理请求的应用,您只需执行 Python 脚本:

entrypoint: python main.py

上面所示的基本 entrypoint 示例只是个学习起点,可能适用于您的 Web 应用,但是,大多数应用将需要进一步配置 WSGI 服务器。在项目的 app.yaml 文件所在的根目录中创建 gunicorn.conf.py 文件(而不是在入口点指定所有设置),并在入口点中指定它:

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

如需了解 Gunicorn 的所有配置值,您可以阅读其文档

工作器

Gunicorn 使用工作器来处理请求。默认情况下,Gunicorn 使用同步工作器。此类工作器与所有 Web 应用都兼容,但每个工作器一次只能处理一个请求。默认情况下,gunicorn 只使用其中一个工作器。这通常会导致您的实例得不到充分利用,并且可能会增加高负载应用的延迟时间。

我们建议您将工作器数量设置为实例的 CPU 核心数的 2 至 4 倍再加一。您可以在 gunicorn.conf.py 中将此字段指定为:

import multiprocessing

workers = multiprocessing.cpu_count() * 2 + 1

另外,一些主要受 I/O 约束的 Web 应用可以通过使用不同的工作器类别来实现性能的提升。 如果您的工作器类需要其他依赖项(例如 gevent 或 tornado),则需要在应用的 requirements.txt 中声明这些依赖项。

HTTPS 和转发代理

App Engine 在负载均衡器上终止 HTTPS 连接,并将请求转发给应用。大多数应用不需要知道请求是否通过 HTTPS 发送,但需要此信息的应用应将 Gunicorn 配置为信任其 gunicorn.conf.py 中的 App Engine 代理:

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"