本页面介绍了如何在标准环境中安装和使用适用于 Python 3 运行时的旧版捆绑服务。您的应用必须通过 Python 3 版 App Engine 服务 SDK 访问捆绑服务。
准备工作
- 请参阅您可以在 Python 运行时中调用的旧版捆绑服务 API 列表。
- 在开始将项目迁移到 Python 3 之前,请参阅运行时迁移概览以及使用旧版捆绑服务时的迁移注意事项。
安装 App Engine 服务 SDK
如需安装 App Engine 服务 SDK,请按照以下步骤操作:
将以下行添加到
requirements.txt
文件,以在应用中添加 SDK:appengine-python-standard>=1.0.0
您可以在 GitHub 上的
appengine-python-standard
代码库和 PyPI 下找到 SDK。在主 Python 脚本中添加以下代码。此代码会创建 WSGI 中间件,该中间件会设置启用 API 调用所需的变量。
Flask
from flask import Flask from google.appengine.api import wrap_wsgi_app app = Flask(__name__) app.wsgi_app = wrap_wsgi_app(app.wsgi_app)
Django
from DJANGO_PROJECT_NAME.wsgi import application from google.appengine.api import wrap_wsgi_app app = wrap_wsgi_app(application)
金字塔
from pyramid.config import Configurator from google.appengine.api import wrap_wsgi_app config = Configurator() # make configuration settings app = config.make_wsgi_app() app = wrap_wsgi_app(app)
WSGI
import google.appengine.api def app(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) yield b'Hello world!\n' app = google.appengine.api.wrap_wsgi_app(app)
在部署应用之前,将以下行添加到
app.yaml
文件:app_engine_apis: true
如需部署应用,请使用
gcloud app deploy
命令。
迁移注意事项
如果您要迁移到 Python 3 运行时,并且您的应用使用旧版捆绑服务,则您应该了解以下注意事项。
测试
如需在 Python 3 应用中本地测试旧版捆绑服务功能,请使用本地开发服务器。运行 dev_appserver.py
命令时,您必须设置 --runtime_python_path
参数以包含 Python 3 解释器的路径。
例如:
python3 CLOUD_SDK_ROOT/bin/dev_appserver.py --runtime_python_path=/usr/bin/python3
您还可以将参数设置为以英文逗号分隔的 [RUNTIME_ID]=[PYTHON_INTERPRETER_PATH]
对列表。例如:
python3 CLOUD_SDK_ROOT/bin/dev_appserver.py --runtime_python_path="python27=/user/bin/python2.7,python3=/usr/bin/python3"
pickle 兼容性
包括 Memcache、Cloud NDB 和 deferred 在内的共享服务使用 pickle 模块来序列化和共享 Python 对象。如果您的 App Engine 环境同时使用 Python 2 和 Python 3(在迁移中很常见),您必须确保由一个 Python 版本编写的共享序列化对象可由另一个版本重构。您可以在指南中找到关于实现跨版本 pickle 兼容性的指导。
默认情况下,Python 3 使用 Python 2 不支持的 pickle 协议。如果应用尝试在 Python 2 环境中重构在 Python 3 环境中编写的 Python 对象,则可能会导致失败。为避免此问题,请根据需要在 Python 3 应用的 app.yaml
文件中设置以下环境变量:
- 对于使用 Memcache 的应用(包括使用 NDB 的应用),请设置:
MEMCACHE_USE_CROSS_COMPATIBLE_PROTOCOL: 'True'
- 对于使用 NDB 连接到 Datastore 的应用,请设置:
NDB_USE_CROSS_COMPATIBLE_PICKLE_PROTOCOL: 'True'
- 对于使用 deferred 的应用,请设置:
DEFERRED_USE_CROSS_COMPATIBLE_PICKLE_PROTOCOL: 'True'
在 Python 2 中,string
对象包含一系列 8 位字节值。在 Python 3 中,string
对象包含一系列 Unicode 字符。默认情况下,Python 3 pickle 会将 Python 3 string
转换为 ASCII,从而将 Python 2 string
转换为 Unicode。如果值超出 0 到 127 的 ASCII 字符范围,这可能会导致错误。Memcache 支持替换此默认映射。
from google.appengine.api import memcache
import six.moves.cPickle as pickle
def _unpickle_factory(file):
return pickle.Unpickler(file, encoding='latin1')
memcache.setup_client(memcache.Client(unpickler=_unpickle_factory))
latin1
编码定义了 Python 2 string
中每个字节的 256 个可能值中每一个的映射。这可以防止解码错误。但是,如果您的 Python 2 string
包含 latin1
范围之外的实际 Unicode 数据(例如从文件中读取的数据),则 cPickle 将无法正确映射数据。因此,请务必更新您的 Python 2 代码,以便为您 pickle 的对象使用 unicode
对象(而非 string
对象)保存 Unicode 数据。兼容性指南包含所需更新的详细信息。
上述更新 Python 2 代码以生成与 Python 3 兼容的序列化的方法针对短期有效的序列化,例如存储在 Memcache 中的序列化。您可能需要在迁移过程中更新或重写长期有效的 Python 2 序列化,例如存储在 Datastore 中的序列化。例如,使用 google.appengine.ext.ndb.model.PickleProperty
编写的序列化可能需要升级。
如需详细了解限制和不太常见的问题,请参阅兼容性指南。
Web 框架
Python 3 中不捆绑也不支持 webapp2
,如需使用任何 WSGI 兼容框架(如 Flask),应用需要重写。
建议使用以下迁移策略。首先,在 Python 2.7 中,将 Python 2.7 应用中的 webapp2
替换为 Flask(或其他 Web 框架,例如 Django、Pyramid、Bottle 或 web.py)。然后,在更新后的应用稳定后,将代码迁移到 Python 3 并使用适用于 Python 3 的 App Engine 进行部署和测试。
如需查看将使用 webapp2
的 Python 2.7 应用转换为使用 Flask 框架的示例,请参阅这些其他资源。
使用处理程序
一个 Python 3 应用只能有一个关联脚本,因此,如果您的 app.yaml
有多个将网址映射到不同的脚本的 script
处理程序,您需要将这些脚本合并成一个处理网址路由的脚本。
以下示例展示了各运行时的 app.yaml
文件中的处理程序差异。
Python 2
runtime: python27 api_version: 1 threadsafe: true handlers: - url: / script: home.app - url: /index\.html script: home.app - url: /stylesheets static_dir: stylesheets - url: /(.*\.(gif|png|jpg))$ static_files: static/\1 upload: static/.*\.(gif|png|jpg)$ - url: /admin/.* script: admin.app login: admin - url: /.* script: not_found.app
Python 3
runtime: python312
app_engine_apis: true
handlers:
- url: /stylesheets
static_dir: stylesheets
- url: /(.*\.(gif|png|jpg))$
static_files: static/\1
upload: static/.*\.(gif|png|jpg)$
- url: /admin/.*
script: auto
login: admin
您的 Python 3 应用必须处理网址路由(例如,使用 Flask 修饰器)。
如果您要使用多个具有不同网址格式的 script
处理程序,或者要在处理程序中使用其他属性,则每个处理程序必须指定 script: auto
。
您也可以通过在 app.yaml
文件中指定 entrypoint
字段来替换默认启动行为。
如需详细了解如何使用特定处理程序,请参阅 Blobstore 概览、延迟概览和邮件概览。
线程安全(性)
应用被视为是线程安全的。 必须在请求线程上进行 API 调用。 如果您在应用启动时使用旧版捆绑服务 API,则可能会导致安全错误。
如需了解详情,请参阅使用 Python 版旧版捆绑服务时的安全错误。
使用 URL Fetch
如需使用 Python 的网址提取,您需要明确调用网址提取库。
如果您的 Python 3 应用使用 URL Fetch API,则在您的应用向另一个 App Engine 应用发送请求时添加 X-Appengine-Inbound-Appid
请求标头。这样,接收方应用便可验证调用方应用的身份。如需了解详情,请参阅迁移出站请求。
示例 (App Engine ndb
)
下面是一个基本的 Python 2 应用,它使用 App Engine ndb
注册页面访问功能来访问 Datastore。其配套是 Python 3 等效应用,其中使用的 webapp2
已替换为 Flask,并且已实现上述访问 Python 3 捆绑服务所需的更改。
Python 2 (webapp2
)
Python 3 (Flask)
这两个应用都可以在 Python App Engine 迁移内容的开源代码库中找到(代码示例、视频、codelabs),具体来说分别在 mod0
和 mod1b
文件夹中。