1. 概览
这一系列的 Codelab(自定进度的动手教程)旨在帮助开发者了解部署应用时可用的各种选项。在本 Codelab 中,您将学习如何将 Google Cloud Translation API 与 Python 搭配使用,以及如何在本地运行或部署到 Cloud 无服务器计算平台(App Engine、Cloud Functions 或 Cloud Run)。本教程的代码库中提供的示例应用可以通过(至少)八种不同的方式进行部署,只需进行少量配置更改:
- 本地 Flask 服务器 (Python 2)
- 本地 Flask 服务器 (Python 3)
- App Engine (Python 2)
- App Engine (Python 3)
- Cloud Functions (Python 3)
- Cloud Run(通过 Docker 使用 Python 2)
- Cloud Run(通过 Docker 使用 Python 3)
- Cloud Run(通过 Cloud Buildpack 使用 Python 3)
此 Codelab 重点介绍如何将此应用部署到上述加粗的平台。
您将了解如何
- 使用 Google Cloud API,尤其是 Cloud Translation API(高级版/v3)
- 在本地运行基本 Web 应用或将其部署到 Cloud 无服务器计算平台
所需条件
- 具有有效的 Cloud Billing 账号的 Google Cloud 项目
- 已安装 Flask 以便在本地运行,或者已启用 Cloud 无服务器计算平台以进行基于云的部署
- 基本 Python 技能
- 基本操作系统命令的实践知识
调查问卷
您打算如何使用本教程?
您如何评价使用 Python 的体验?
您如何评价自己在使用 Google Cloud 服务方面的经验水平?
2. 设置和要求
自定进度的环境设置
- 登录 Google Cloud 控制台,然后创建一个新项目或重复使用现有项目。如果您还没有 Gmail 或 Google Workspace 账号,则必须创建一个。



- 项目名称是此项目参与者的显示名称。它是 Google API 尚未使用的字符串,您可以随时对其进行更新。
- 项目 ID 在所有 Google Cloud 项目中必须是唯一的,并且不可变(一经设置便无法更改)。Cloud Console 会自动生成一个唯一字符串;通常情况下,您无需关注该字符串。在大多数 Codelab 中,您都需要引用项目 ID(它通常标识为
PROJECT_ID),因此如果您不喜欢某个 ID,请再生成一个随机 ID,还可以尝试自己创建一个,并确认是否可用。然后,项目创建后,ID 会处于“冻结”状态。 - 第三个值是一些 API 使用的项目编号。如需详细了解所有这三个值,请参阅文档。
- 接下来,您需要在 Cloud Console 中启用结算功能,才能使用 Cloud 资源/API。运行此 Codelab 应该不会产生太多的费用(如果有费用的话)。要关闭资源以避免产生超出本教程范围的费用,请按照此 Codelab 末尾提供的任何“清理”说明操作。Google Cloud 的新用户符合参与 $300 USD 免费试用计划的条件。
3. 启用 Translation API
对于我们的示例应用,您将启用 Cloud Translation API 和 App Engine 服务,而不是使用下面提供的类似说明。
启用 Cloud API
简介
无论您要在应用中使用哪个 Google API,都必须先启用相应 API。以下示例展示了启用 Cloud Vision API 的两种方法。了解如何启用一个 Cloud API 后,您便能够启用其他 API,因为过程类似。
方法 1:通过 Cloud Shell 或命令行界面
虽然通过 Cloud 控制台启用 API 更为常见,但有些开发者更喜欢通过命令行完成所有操作。为此,您需要查找 API 的“服务名称”。它看起来像一个网址:SERVICE_NAME.googleapis.com。您可以在支持的产品图表中找到这些信息,也可以通过 Google Discovery API 以编程方式查询这些信息。
掌握这些信息后,您可以使用 Cloud Shell(或安装了 gcloud 命令行工具的本地开发环境)启用 API,如下所示:
gcloud services enable SERVICE_NAME.googleapis.com
例如,以下命令会启用 Cloud Vision API:
gcloud services enable vision.googleapis.com
此命令会启用 App Engine:
gcloud services enable appengine.googleapis.com
您还可以通过一个请求启用多个 API。例如,以下命令行可启用 Cloud Run、Cloud Artifact Registry 和 Cloud Translation API:
gcloud services enable artifactregistry.googleapis.com run.googleapis.com translate.googleapis.com
方法 2:通过 Cloud 控制台
您还可以在 API 管理器中启用 Vision API。在 Cloud 控制台中,前往 API 管理器,然后选择库。

如果您想启用 Cloud Vision API,请在搜索栏中开始输入“vision”,系统会显示与您目前输入的内容匹配的所有内容:

选择您要启用的 API,然后点击启用:

费用
虽然许多 Google API 可以免费使用,但使用 Google Cloud 产品和 API 不是免费的。启用 Cloud API 时,系统可能会要求您提供有效的结算账号。不过,请务必注意,部分 Google Cloud 产品提供“始终免费”层级(每日/每月),只有超出此层级才会产生结算费用;否则,系统不会向您的信用卡(或指定的付款方式)收取费用。
用户应在启用任何 API 之前参考其价格信息,尤其要注意该 API 是否有免费层级,如果有,免费层级是什么。如果您要启用 Cloud Vision API,则应查看其价格信息页面。Cloud Vision 确实有免费配额,只要您在每个月内总共不超过其限额,就不会产生任何费用。
Google API 的价格和免费层级各不相同。示例:
- Google Cloud/GCP - 每种产品的结算方式各不相同,一般按 vCPU 周期、存储空间用量、内存用量或按用量付费;请参阅上文中的免费层级信息。
- Google 地图 - 提供一套 API,并为用户提供总计每月 200 美元的免费赠金。
- Google Workspace(旧称 G Suite)API - 提供免费使用(在一定限额内),费用包含在 Workspace 月度订阅费用中,因此使用 Gmail、Google 云端硬盘、日历、文档、表格和幻灯片 API 不会直接产生费用。
不同 Google 产品的结算方式各不相同,因此请务必参阅相应 API 的文档以了解相关信息。
摘要
现在,您已经了解如何启用 Google API,请前往 API 管理器,然后同时启用 Cloud Translation API 和 App Engine 服务(如果您尚未启用),前者是因为我们的应用将使用它,后者是因为您要部署 App Engine 应用。如果您想通过命令行执行此操作,请改为发出以下命令:
gcloud services enable appengine.googleapis.com translate.googleapis.com
虽然其每月配额未列在总体“始终免费”层级摘要页面中,但Translation API 的价格页面指出,所有用户每月都会获得固定数量的翻译字符。如果您未超出该阈值,则不应因使用该 API 而产生任何费用。如果还有其他与 Google Cloud 相关的费用,我们将在最后的“清理”部分中讨论。
4. 获取示例应用代码
在本地或 Cloud Shell 中克隆代码库中的代码(使用 git clone 命令),或从其绿色代码按钮下载 ZIP 文件,如以下屏幕截图所示:

现在,您已准备好一切,请创建该文件夹的完整副本以完成本教程,因为本教程可能涉及删除或更改文件。如果您想进行其他部署,可以复制原始部署,这样就无需再次克隆或下载。
5. 示例应用导览
此示例应用是 Google 翻译的简单衍生应用,可提示用户输入英文文本,并接收该文本的等效西班牙语译文。现在,打开 main.py 文件,以便了解其运作方式。省略有关许可的注释行后,顶部和底部如下所示:
from flask import Flask, render_template, request
import google.auth
from google.cloud import translate
app = Flask(__name__)
_, PROJECT_ID = google.auth.default()
TRANSLATE = translate.TranslationServiceClient()
PARENT = 'projects/{}'.format(PROJECT_ID)
SOURCE, TARGET = ('en', 'English'), ('es', 'Spanish')
# . . . [translate() function definition] . . .
if __name__ == '__main__':
import os
app.run(debug=True, threaded=True, host='0.0.0.0',
port=int(os.environ.get('PORT', 8080)))
- 导入操作会引入 Flask 功能、
google.auth模块和 Cloud Translation API 客户端库。 - 全局变量表示 Flask 应用、云项目 ID、Translation API 客户端、Translation API 调用的父“位置路径”,以及源语言和目标语言。在本例中,这些值是英语 (
en) 和西班牙语 (es),但您可以随意将这些值更改为 Cloud Translation API 支持的其他语言代码。 - 底部的
if大块代码用于本教程中的在本地运行此应用,它利用 Flask 开发服务器来提供我们的应用。此部分还用于 Cloud Run 部署教程,以防 Web 服务器未捆绑到容器中。系统会要求您启用将服务器捆绑到容器中,但如果您忽略了这一点,应用代码会回退到使用 Flask 开发服务器。(App Engine 或 Cloud Functions 不存在此问题,因为它们是基于源代码的平台,这意味着 Google Cloud 提供并运行默认的网络服务器。)
最后,main.py 的中间是应用的核心,即 translate() 函数:
@app.route('/', methods=['GET', 'POST'])
def translate(gcf_request=None):
"""
main handler - show form and possibly previous translation
"""
# Flask Request object passed in for Cloud Functions
# (use gcf_request for GCF but flask.request otherwise)
local_request = gcf_request if gcf_request else request
# reset all variables (GET)
text = translated = None
# if there is data to process (POST)
if local_request.method == 'POST':
text = local_request.form['text']
data = {
'contents': [text],
'parent': PARENT,
'target_language_code': TARGET[0],
}
# handle older call for backwards-compatibility
try:
rsp = TRANSLATE.translate_text(request=data)
except TypeError:
rsp = TRANSLATE.translate_text(**data)
translated = rsp.translations[0].translated_text
# create context & render template
context = {
'orig': {'text': text, 'lc': SOURCE},
'trans': {'text': translated, 'lc': TARGET},
}
return render_template('index.html', **context)
主要函数负责获取用户输入,并调用 Translation API 来完成繁重的工作。我们来详细了解一下:
- 使用
local_request变量检查请求是否来自 Cloud Functions。Cloud Functions 会发送自己的 Flask Request 对象,而所有其他对象(在本地运行或部署到 App Engine 或 Cloud Run)将直接从 Flask 获取请求对象。 - 重置表单的基本变量。这主要适用于 GET 请求,因为 POST 请求将包含替换这些数据的其他数据。
- 如果是 POST,则获取要翻译的文本,并创建一个表示 API 元数据要求的 JSON 结构。然后调用该 API,如果用户使用的是旧版库,则回退到该 API 的先前版本。
- 无论如何,将实际结果 (POST) 或无数据 (GET) 格式化为模板上下文并进行渲染。
应用的视觉部分位于模板 index.html 文件中。它会显示之前翻译的所有结果(否则为空白),然后显示一个表单,要求用户提供要翻译的内容:
<!doctype html>
<html><head><title>My Google Translate 1990s</title><body>
<h2>My Google Translate (1990s edition)</h2>
{% if trans['text'] %}
<h4>Previous translation</h4>
<li><b>Original</b>: {{ orig['text'] }} (<i>{{ orig['lc'][0] }}</i>)</li>
<li><b>Translated</b>: {{ trans['text'] }} (<i>{{ trans['lc'][0] }}</i>)</li>
{% endif %}
<h4>Enter <i>{{ orig['lc'][1] }}</i> text to translate to <i>{{ trans['lc'][1] }}</i>:</h4>
<form method="POST"><input name="text"><input type="submit"></form>
</body></html>
6. 安装本地软件包/依赖项(到 lib 中)
如前所述,此示例应用使用 Flask 微型 Web 框架和适用于 Python 的 Google Cloud Translation API 客户端库。使用以下 pip(或 pip3)命令安装和更新 pip 以及这对软件包:
pip install -t lib -r requirements.txt
运行上述命令后,您会看到安装输出,其内容可能如下所示:
$ pip install -t lib -r requirements.txt
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality.
Collecting flask>=1.1.2
Using cached Flask-1.1.4-py2.py3-none-any.whl (94 kB)
Collecting google-cloud-translate>=2.0.1
Using cached google_cloud_translate-2.0.2-py2.py3-none-any.whl (91 kB)
Collecting click<8.0,>=5.1
Using cached click-7.1.2-py2.py3-none-any.whl (82 kB)
Collecting Jinja2<3.0,>=2.10.1
Using cached Jinja2-2.11.3-py2.py3-none-any.whl (125 kB)
Collecting Werkzeug<2.0,>=0.15
Using cached Werkzeug-1.0.1-py2.py3-none-any.whl (298 kB)
Collecting itsdangerous<2.0,>=0.24
Using cached itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)
Collecting google-api-core[grpc]<2.0.0dev,>=1.15.0
Downloading google_api_core-1.29.0-py2.py3-none-any.whl (93 kB)
|████████████████████████████████| 93 kB 2.1 MB/s
Collecting google-cloud-core<2.0dev,>=1.1.0
Using cached google_cloud_core-1.6.0-py2.py3-none-any.whl (28 kB)
Collecting MarkupSafe>=0.23
Using cached MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl (17 kB)
Collecting protobuf>=3.12.0
Downloading protobuf-3.17.2-cp27-cp27m-macosx_10_9_x86_64.whl (958 kB)
|████████████████████████████████| 958 kB 21.6 MB/s
Collecting futures>=3.2.0; python_version < "3.2"
Using cached futures-3.3.0-py2-none-any.whl (16 kB)
Collecting six>=1.13.0
Using cached six-1.16.0-py2.py3-none-any.whl (11 kB)
Collecting packaging>=14.3
Using cached packaging-20.9-py2.py3-none-any.whl (40 kB)
Collecting googleapis-common-protos<2.0dev,>=1.6.0
Using cached googleapis_common_protos-1.52.0-py2.py3-none-any.whl (100 kB)
Collecting requests<3.0.0dev,>=2.18.0
Using cached requests-2.25.1-py2.py3-none-any.whl (61 kB)
Collecting google-auth<2.0dev,>=1.25.0
Using cached google_auth-1.30.1-py2.py3-none-any.whl (146 kB)
Collecting pytz
Using cached pytz-2021.1-py2.py3-none-any.whl (510 kB)
Collecting setuptools>=40.3.0
Using cached setuptools-44.1.1-py2.py3-none-any.whl (583 kB)
Collecting grpcio<2.0dev,>=1.29.0; extra == "grpc"
Using cached grpcio-1.38.0-cp27-cp27m-macosx_10_10_x86_64.whl (3.8 MB)
Collecting pyparsing>=2.0.2
Using cached pyparsing-2.4.7-py2.py3-none-any.whl (67 kB)
Collecting chardet<5,>=3.0.2
Using cached chardet-4.0.0-py2.py3-none-any.whl (178 kB)
Collecting urllib3<1.27,>=1.21.1
Using cached urllib3-1.26.5-py2.py3-none-any.whl (138 kB)
Collecting idna<3,>=2.5
Using cached idna-2.10-py2.py3-none-any.whl (58 kB)
Collecting certifi>=2017.4.17
Downloading certifi-2021.5.30-py2.py3-none-any.whl (145 kB)
|████████████████████████████████| 145 kB 61.1 MB/s
Collecting pyasn1-modules>=0.2.1
Using cached pyasn1_modules-0.2.8-py2.py3-none-any.whl (155 kB)
Collecting rsa<4.6; python_version < "3.6"
Using cached rsa-4.5-py2.py3-none-any.whl (36 kB)
Collecting cachetools<5.0,>=2.0.0
Using cached cachetools-3.1.1-py2.py3-none-any.whl (11 kB)
Collecting enum34>=1.0.4; python_version < "3.4"
Using cached enum34-1.1.10-py2-none-any.whl (11 kB)
Collecting pyasn1<0.5.0,>=0.4.6
Using cached pyasn1-0.4.8-py2.py3-none-any.whl (77 kB)
Installing collected packages: click, MarkupSafe, Jinja2, Werkzeug, itsdangerous, flask, six, protobuf, futures, pyparsing, packaging, googleapis-common-protos, chardet, urllib3, idna, certifi, requests, pyasn1, pyasn1-modules, rsa, cachetools, setuptools, google-auth, pytz, enum34, grpcio, google-api-core, google-cloud-core, google-cloud-translate
ERROR: pip's legacy dependency resolver does not consider dependency conflicts when selecting packages. This behaviour is the source of the following dependency conflicts.
matplotlib 1.3.1 requires nose, which is not installed.
matplotlib 1.3.1 requires tornado, which is not installed.
Successfully installed Jinja2-2.11.3 MarkupSafe-1.1.1 Werkzeug-1.0.1 cachetools-3.1.1 certifi-2021.5.30 chardet-4.0.0 click-7.1.2 enum34-1.1.10 flask-1.1.4 futures-3.3.0 google-api-core-1.29.0 google-auth-1.30.1 google-cloud-core-1.6.0 google-cloud-translate-2.0.2 googleapis-common-protos-1.52.0 grpcio-1.38.0 idna-2.10 itsdangerous-1.1.0 packaging-20.9 protobuf-3.17.2 pyasn1-0.4.8 pyasn1-modules-0.2.8 pyparsing-2.4.7 pytz-2021.1 requests-2.25.1 rsa-4.5 setuptools-44.1.1 six-1.16.0 urllib3-1.26.5
7. 部署服务
如需将翻译服务部署到 Python 2 App Engine,请运行以下命令:
gcloud app deploy
输出应如下所示,并提供一些后续步骤的提示:
$ gcloud app deploy Services to deploy: descriptor: [/private/tmp/nebulous-serverless-python/app.yaml] source: [/private/tmp/nebulous-serverless-python] target project: [PROJECT_ID] target service: [default] target version: [20210422t161025] target url: [https://PROJECT_ID.appspot.com] Do you want to continue (Y/n)? Beginning deployment of service [default]... ╔════════════════════════════════════════════════════════════╗ ╠═ Uploading 1290 files to Google Cloud Storage ═╣ ╚════════════════════════════════════════════════════════════╝ File upload done. Updating service [default]...done. Setting traffic split for service [default]...done. Deployed service [default] to [https://PROJECT_ID.appspot.com] You can stream logs from the command line by running: $ gcloud app logs tail -s default To view your application in the web browser run: $ gcloud app browse
现在,您的应用已在全球范围内推出,您应该可以通过部署输出中提供的网址(包含您的项目 ID)访问该应用:

翻译一些内容,看看效果如何!

8. 总结
恭喜!您已经学会了如何启用 Cloud Translation API、获取必要的凭据,以及将简单的 Web 应用部署到 Python 2 App Engine!您可以点击代码库中的此表格,详细了解此部署。
清理
借助 Cloud Translation API,您可以每月免费翻译一定数量的字符。App Engine 也有免费配额,Cloud Functions 和 Cloud Run 也是如此。如果超出任一限制,您都需要付费。如果您打算继续学习下一个 Codelab,则无需关闭应用。
不过,如果您尚未准备好学习下一个教程,或者担心互联网会发现您刚刚部署的应用,请停用 App Engine 应用、删除 Cloud Function 或停用 Cloud Run 服务,以免产生费用。准备好继续学习下一个 Codelab 后,您可以重新启用该功能。另一方面,如果您不打算继续使用此应用或其他 Codelab,并想彻底删除所有内容,可以关停项目。
此外,部署到 Google Cloud 无服务器计算平台会产生少量构建和存储费用。Cloud Build 和 Cloud Storage 都有各自的免费配额。为了提高透明度,Cloud Build 会构建您的应用映像,然后将其存储在 Cloud Container Registry 或其后继产品 Artifact Registry 中。存储该映像会占用部分配额,将该映像传输到服务时产生的网络出站流量也会占用部分配额。不过,您居住的地区可能没有此类免费层级,因此请注意存储空间用量,以尽可能减少潜在费用。
9. 其他资源
在以下部分中,您可以找到其他读物以及推荐的练习,以巩固您通过完成本教程获得的知识。
其他研究
现在,您已经积累了一些 Translation API 使用经验,接下来让我们做一些额外的练习,进一步提升您的技能。如需继续学习路线,请修改我们的示例应用,以实现以下功能:
- 完成此 Codelab 的所有其他版本,以便在本地运行或部署到 Google Cloud 无服务器计算平台(请参阅代码库 README)。
- 使用其他编程语言完成本教程。
- 更改此应用以支持不同的源语言或目标语言。
- 升级此应用,以便能够将文本翻译成多种语言;更改模板文件,使其包含支持的目标语言下拉菜单。
了解详情
Google App Engine
- App Engine 首页
- App Engine 文档
- Python 3 App Engine 快速入门
- App Engine 的默认服务账号
- Python 2 App Engine(标准)运行时
- Python 3 App Engine(标准)运行时
- Python 2 和 3 App Engine(标准)运行时之间的差异
- Python 2 到 3 App Engine(标准)迁移指南
Google Cloud Functions
Google Cloud Run
Google Cloud Buildpacks、Container Registry、Artifact Registry
- Cloud Buildpack 公告
- Cloud Buildpack 代码库
- Cloud Artifact Registry 首页
- Cloud Artifact Registry 文档
- Cloud Container Registry 首页
- Cloud Container Registry 文档
Google Cloud Translation 和 Google 机器学习套件
- Cloud Translation 首页
- Cloud Translation 文档
- Translation API 价格页面
- 所有云 AI/机器学习“构建块”API
- Google 机器学习套件(适用于移动设备的云 AI/机器学习 API 子集)
- Google ML Kit Translation API
其他 Google Cloud 产品/网页
Python 和 Flask
许可
本教程已获得知识共享署名 2.0 通用许可授权,而相应代码库中的源代码已获得 Apache 2 许可授权。