迁移到 Python 3 运行时

Python 2.7 已于 2024 年 1 月 31 日达到支持终止期限。现有的 Python 2.7 应用将继续运行并接收流量。但是,App Engine 可能会阻止重新部署使用支持终止日期之后的运行时的应用。我们建议您按照本页面中的指导迁移到最新支持的 Python 版本。

迁移到 Python 3 运行时后,您可以使用最新的语言功能,并构建可移植性更强的应用(具有惯用的代码)。Python 3 运行时使用 Python Software Foundation 提供的最新版开源 Python 解释器。在 Python 3 运行时中构建的应用可以通过在 requirements.txt 文件中声明依赖项,在应用中使用 Python 丰富的软件包和框架生态系统,包括那些使用 C 代码的应用。

运行时迁移过程概览

我们建议您采用以下增量式运行时迁移方法,借助此方法,您可以在迁移过程中维护一个功能齐全和可测试的应用:

  1. 升级您的应用,使其兼容 Python 3。

    有几种解决方案可帮助您完成此次升级。例如,使用 SixPython-FuturePython-Modernize

    如需详细了解迁移过程的这一步,请参阅 Python Software Foundation 文档网站上的将 Python 2 代码移植到 Python 3

  2. 为应用使用的所有 App Engine 捆绑服务选择以下实现策略之一:

    1. 将 Python 2 应用中的旧版捆绑服务迁移到未绑定 Google Cloud 服务、第三方服务或其他推荐的替代服务

    2. 继续在 Python 3 应用中使用旧版捆绑服务。这种方法可让您灵活地在迁移周期的后期迁移到非捆绑服务。

    请务必在迁移每项服务后测试您的应用。

  3. 为 Python 3 运行时准备 App Engine 配置文件。 多项重要更改影响了 app.yaml 中的配置设置,这些配置包括但不限于:

    • 现在假定应用的线程安全。如果应用不是线程安全的,则应将 app.yaml 中的 max_concurrent_requests 设置为 1。此设置可能会导致创建的实例数多于线程安全应用所需的数量,并产生不必要的费用。
    • app.yaml 文件不会再将请求路由到您的脚本。因此,您需要使用具有应用内路由的 Web 框架,并更新或移除 app.yaml 中的所有 script 处理程序。 有关如何使用 Flask 框架执行此操作的示例,请参阅 GitHub 中的 App Engine 迁移指南代码示例

      如需详细了解如何更改此配置文件和其他配置文件,请参阅配置文件部分。

  4. 在第二代运行时中,应用日志不再嵌套在请求日志中。如需在 Logs Explorer 中显示请求和应用日志的嵌套视图,您还需要执行其他步骤。如需了解详情,请参阅迁移到 Cloud Logging

  5. 在 Python 3 环境中测试和部署升级后的应用。

    通过所有测试后,将升级后的应用部署到 App Engine,但阻止流量自动路由到新版本。使用流量拆分,将 Python 2 运行时中应用的流量缓慢迁移到 Python 3 运行时中的应用中。如果遇到问题,您可以将所有流量路由到一个稳定的版本,直到问题得到解决。

有关如何将 Python 2 应用转换为 Python 3 的示例,请参阅这些其他资源

Python 2 和 Python 3 运行时的主要区别

在运行时迁移过程中,您需要执行的多数更改都是因为 Python 2 和 Python 3 运行时之间存在的以下区别:

内存用量差异

与第一代运行时相比,第二代运行时的内存用量基准更高。这是由多种因素造成的,例如基础映像版本不同,以及两代在计算内存用量的方式上存在差异。

第二代运行时在计算实例内存用量时,会将应用进程的内存用量与内存中动态缓存的应用文件数量相加。为避免内存密集型应用因超出内存限制而关停实例,请升级到具有更多内存的更大实例类

CPU 使用率差异

第二代运行时在实例冷启动时会看到更高的 CPU 使用率基准。根据应用的扩缩配置,这可能会导致意外的副作用,例如,如果应用配置为根据 CPU 利用率进行扩缩,则实例数会高于预期。为避免此问题,请查看并测试应用扩缩配置,以确保实例数在可接受的范围内。

请求标头差异

第一代运行时允许将带有下划线(例如 X-Test-Foo_bar)的请求标头转发给应用。第二代运行时将 Nginx 引入了主机架构。由于此更改,第二代运行时配置为自动移除带有下划线 (_) 的标头。为防止出现应用问题,请避免在应用请求标头中使用下划线。

Gunicorn 工作器差异

对于 Python 3+ 运行时,Gunicorn 工作器的数量会直接影响内存用量。内存用量的增加与工作器数量的增加成正比。如需减少内存消耗,请考虑减少 Gunicorn 工作器的数量。如需了解如何配置 Gunicorn 工作器数量,请参阅入口点最佳做法

Python 2 和 Python 3 之间的兼容性问题

当 Python 3 在 2008 年首次发布时,该语言引入了数个向后不兼容的更改。其中一些更改只需要对代码进行小幅更新,例如将 print 语句更改为 print() 函数。还有一些更改可能需要大幅更新代码,例如更新处理二进制数据、文本和字符串的方式。

许多流行的开源库,包括 Python 标准库,在从 Python 2 迁移到 Python 3 时也发生了变化。

Python 3 运行时中的 App Engine 捆绑服务

为了减少迁移工作量和复杂性,App Engine 标准环境允许您在 Python 3 运行时中访问许多旧版捆绑服务和 API,例如 Memcache。您的 Python 3 应用可以通过语言惯用库调用捆绑服务 API,并访问与 Python 2 运行时相同的功能。

您还可以选择使用 Google Cloud 产品,其可提供与旧版捆绑服务类似的功能。我们建议您考虑迁移到非捆绑的 Google Cloud 产品,这样可以充分利用持续的改进和新功能。

对于在 Google Cloud 中未作为单独产品提供的捆绑服务(如图片处理、搜索和消息传递),您可以使用我们推荐的第三方提供商或其他解决方法

配置文件

在 App Engine 标准环境的 Python 3 运行时中运行应用之前,可能需要更改该 App Engine 使用的一些配置文件:

需要 Web 框架才能路由对动态内容的请求

在 Python 2 运行时中,您可以在 app.yaml 文件中创建网址处理程序,在请求特定网址或网址格式时指定运行哪个应用

在 Python 3 运行时中,要路由动态内容请求,您的应用需要使用 Flask 或 Django 等 Web 框架,而不是使用 app.yaml 中的网址处理程序。对于静态内容,您可以继续在您应用的 app.yaml 文件中创建网址处理程序

仅包含静态内容的应用

在 App Engine 上托管静态 Web 应用时,您可以在 app.yaml 文件中指定处理程序,以将网址映射到静态文件。

在 Python 2 中,如果请求与 app.yaml 文件中指定的任何处理程序不匹配,则 App Engine 会返回 404 错误代码。

在 Python 3 中,如果请求与任何处理程序不匹配,则 App Engine 会查找 main.py 文件;如果找不到 main.py 文件,则会返回 5xx 错误。由于仅包含静态内容的 App Engine 应用不需要 main.py 文件,因此除了在应用日志中看到实例启动错误外,大多数用户还会看到此错误。

为确保在没有任何静态处理程序匹配时返回 404 错误的相同行为,并避免日志出错,您可以执行以下任一操作:

  • app.yaml 文件中添加一个指向空目录的无限别名静态处理程序
  • main.py 文件中添加一个简单的动态应用,以返回 404 错误

使用各个选项的示例:

app.yaml

在根应用目录中创建一个空目录,例如 empty/。在 app.yaml 文件的处理程序部分的末尾创建新的处理程序,以捕获所有其他网址格式,并在 static_filesupload 元素 中指定 empty 目录:

  handlers:
  - url:
    .
    .
    .
  - url: /(.*)$
    static_files: empty/\1
    upload: empty/.*$

main.py

创建 main.py 文件并添加以下代码,以返回 404 错误:

  def app(env, start_response):
    start_response('404 Not Found', [('Content-Type','text/html')])
    return [b"Not Found"]

测试

我们建议您使用与 Python 惯有相关的测试方法,而不是依赖于 dev_appserver。例如,您可以使用 venv 创建一个独立的本地 Python 3 环境。在其中,任何标准的 Python 测试框架都可用于编写单元、集成和系统测试。此外,您还可以考虑设置服务的开发版本,或使用可用于多个 Google Cloud 产品的本地模拟器。

(可选)您可以使用支持 Python 3 的预览版 dev_appserver。如需详细了解此测试功能,请参阅使用本地开发服务器

正在部署

Python 3 不支持通过 appcfg.py 进行部署。请使用 gcloud 命令行工具部署您的应用。

日志记录

Python 3 运行时中的日志记录遵循 Cloud Logging 中的日志记录标准。在 PHP 3 运行时中,应用日志不再与请求日志捆绑,而是分隔在不同的记录中。如需详细了解如何在 Python 3 运行时中读取和写入日志,请参阅日志记录指南

其他迁移资源

如需详细了解如何将 App Engine 应用迁移到独立 Cloud 服务或 Python 3 运行时,请参阅以下 App Engine 资源: