摘要
在此 Codelab 中,您将学习如何将 Python Flask Web 应用部署到 App Engine 柔性环境。此示例应用允许用户上传人脸照片,并了解照片中的人有多大可能感到快乐。该应用使用 Google Cloud API 进行视觉、存储和 Datastore 操作。
关于 App Engine
Google App Engine 应用易于创建、易于维护,并可根据流量和数据存储需求的变化轻松扩缩。使用 App Engine 时,无需维护任何服务器。您只需上传应用,就可以使用了。
App Engine 应用会根据传入的流量自动扩缩。负载均衡、微服务、授权、SQL 和 NoSQL 数据库、流量分配、日志记录、搜索、版本控制、发布和回滚以及安全扫描都是原生支持的,并且高度可自定义。
App Engine 的柔性环境支持以下所有编程语言:C#、Go、Java、Node.js、PHP、Python 和 Ruby。App Engine 柔性环境在 Google Compute Engine 虚拟机上运行的 Docker 容器中运行应用。App Engine 的标准环境是某些语言(包括 Python)的替代选项。App Engine 标准环境会在限制更严格的沙盒环境中运行您的应用。如需了解详情,请参阅选择 App Engine 环境。
学习内容
- 如何将简单的 Web 应用部署到 App Engine 柔性环境
- 如何访问 Vision、Storage 和 Datastore 的 Google Cloud 客户端库
- 如何使用 Google Cloud 控制台和 Google Cloud SDK 管理各种云资源
- 如何使用 Cloud Shell
所需条件
- 熟悉 Python
- 熟悉标准的 Linux 文本编辑器,例如 Vim、Emacs 或 Nano
项目创建
如果您还没有 Google 账号(Gmail 或 Google Apps),则必须创建一个。登录 Google Cloud Platform Console (console.cloud.google.com) 并创建一个新项目:



请记住项目 ID,它在所有 Google Cloud 项目中都是唯一的名称(上述名称已被占用,您无法使用,抱歉!)。它稍后将在此 Codelab 中被称为 PROJECT_ID。
结算
接下来,您需要在 Cloud Console 中启用结算功能,才能使用 Google Cloud 资源。
在此 Codelab 中运行仅花费几美元,但是如果您决定使用更多资源或继续让它们运行,费用可能更高。
Google Cloud Platform 的新用户有资格获享 $300 免费试用。
虽然 Google Cloud 可以从笔记本电脑远程操作,但在此 Codelab 中,我们将使用 Google Cloud Shell,这是一个在云端运行的命令行环境。这个基于 Debian 的虚拟机上已加载您需要的所有开发工具(gcloud、python、virtualenv、pip 等),并提供永久性的 5 GB 主目录。它在 Google Cloud 上运行,可大幅提升网络性能和身份验证。这意味着在本 Codelab 中,您只需要一个浏览器(没错,它适用于 Chromebook)。
如需激活 Google Cloud Shell,只需在开发者控制台中点击右上角的按钮(预配和连接到环境仅需花费一些时间):


在连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且相关项目已设置为您的项目 ID:
gcloud auth list Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project [core] Project = <PROJECT_ID>
如果出于某种原因未设置项目,只需发出以下命令即可:
gcloud config set project <PROJECT_ID>
想查找您的 PROJECT_ID?检查您在设置步骤中使用的项目 ID,或在控制台信息中心查找该 ID:

在 Cloud Shell 的命令行中,运行以下命令以克隆 GitHub 代码库:
git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
将目录更改为 python-docs-samples/codelabs/flex_and_vision:
cd python-docs-samples/codelabs/flex_and_vision
在开始使用 Vision、Storage 和 Datastore API 之前,您必须使用以下命令启用这些 API:
gcloud services enable vision.googleapis.com
gcloud services enable storage-component.googleapis.com
gcloud services enable datastore.googleapis.com
如需向 Vision、Storage 和 Datastore API 发出请求,您需要服务账号凭据。您可以使用 gcloud 工具生成项目中的服务账号凭据。
为您的 PROJECT_ID 设置环境变量,将 [YOUR_PROJECT_ID] 替换为您自己的项目 ID:
export PROJECT_ID=[YOUR_PROJECT_ID]
创建服务账号以在本地测试时访问 Google Cloud API:
gcloud iam service-accounts create codelab \ --display-name "My Codelab Service Account"
为新创建的服务账号授予适当的权限:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:codelab@${PROJECT_ID}.iam.gserviceaccount.com \
--role roles/owner创建服务账号后,请创建服务账号密钥:
gcloud iam service-accounts keys create ~/key.json \
--iam-account codelab@${PROJECT_ID}.iam.gserviceaccount.com此命令会生成一个服务账号密钥,该密钥存储在主目录中名为 key.json 的 JSON 文件中。
使用生成的密钥的绝对路径,在 Cloud Shell 中为您的服务账号密钥设置环境变量:
export GOOGLE_APPLICATION_CREDENTIALS="/home/${USER}/key.json"您可以详细了解如何对 Vision API 进行身份验证。
启动虚拟环境并安装依赖项
使用 virtualenv 创建一个名为 env 的独立 Python 3 环境:
virtualenv -p python3 env
进入新创建的名为 env 的 virtualenv:
source env/bin/activate
使用 pip 从 requirements.txt 文件中安装项目的依赖项:
pip install -r requirements.txt
requirements.txt 文件是项目所需的软件包依赖项列表。上述命令已将所有列出的软件包依赖项下载到 virtualenv。
创建 App Engine 应用
接下来,使用以下命令创建 App Engine 实例:
gcloud app create创建存储分区
首先,将环境变量 CLOUD_STORAGE_BUCKET 设置为您的 PROJECT_ID 的名称。(一般建议将存储分区命名为与 PROJECT_ID 相同的名称,以便于操作)。
export CLOUD_STORAGE_BUCKET=${PROJECT_ID}我们的应用使用 Cloud Storage 存储分区,您需要使用名为 gsutil 的工具从 Cloud Shell 创建该存储分区。运行以下命令,该命令会创建一个与您的 PROJECT_ID 同名的存储分区。
gsutil mb gs://${PROJECT_ID}运行应用
python main.py
应用启动后,点击 Cloud Shell 工具栏中的“网页预览”图标
,然后选择“在端口 8080 上预览”。

浏览器会打开一个标签页,并连接到您刚启动的服务器。您应该会看到与以下类似的内容:

尝试上传包含人脸的照片。点击选择文件按钮,从计算机中选择一张图片,然后点击提交。
上传照片后,您应该会看到类似如下的内容:

示例代码布局
该示例的布局如下:
templates/
homepage.html /* HTML template that uses Jinja2 */
app.yaml /* App Engine application configuration file */
main.py /* Python Flask web application */
requirements.txt /* List of dependencies for the project */main.py
此 Python 文件是一个 Flask Web 应用。该应用允许用户提交照片(最好是人脸照片),这些照片会存储在 Cloud Storage 中,并使用 Cloud Vision API 的人脸检测功能进行分析。每张照片的关键信息都存储在 Datastore(Google Cloud Platform 的 NoSQL 数据库)中,用户每次访问网站时都会访问这些信息。
此应用使用适用于 Storage、Datastore 和 Vision 的 Google Cloud Platform 客户端库。借助这些客户端库,您可以轻松地使用自己偏好的编程语言访问 Cloud API。
我们来看一下代码的一些关键代码段。
顶部的“imports”部分用于导入代码所需的各种软件包。以下是我们如何导入 Datastore、Storage 和 Vision 的 Google Cloud 客户端库:
from google.cloud import datastore
from google.cloud import storage
from google.cloud import vision以下代码用于指定当用户访问网站的根网址时会发生什么情况。我们创建了一个 Datastore 客户端对象,用于访问 Datastore 客户端库。然后,我们对 Datastore 运行查询,以查找种类为 Faces 的实体。最后,我们呈现 HTML 模板,并将从 Datastore 中提取的 image_entities 作为变量传入。
@app.route('/')
def homepage():
# Create a Cloud Datastore client.
datastore_client = datastore.Client()
# Use the Cloud Datastore client to fetch information from Datastore about
# each photo.
query = datastore_client.query(kind='Faces')
image_entities = list(query.fetch())
# Return a Jinja2 HTML template and pass in image_entities as a parameter.
return render_template('homepage.html', image_entities=image_entities)我们来看看如何将实体保存到 Datastore 中。Datastore 是 Google Cloud 的 NoSQL 数据库解决方案。数据存储在称为实体的对象中。每个实体都会分配一个唯一的标识键,该键可以使用种类和键名字符串创建。种类是用于组织实体类型的组织桶。例如,我们可能需要为照片、人物和动物设置种类。
每个实体都可以有多个开发者定义的属性,这些属性可以具有多种类型的值,包括整数、浮点数、字符串、日期或二进制数据。
# Create a Cloud Datastore client.
datastore_client = datastore.Client()
# Fetch the current date / time.
current_datetime = datetime.now()
# The kind for the new entity.
kind = 'Faces'
# The name/ID for the new entity.
name = blob.name
# Create the Cloud Datastore key for the new entity.
key = datastore_client.key(kind, name)
# Construct the new entity using the key. Set dictionary values for entity
# keys blob_name, storage_public_url, timestamp, and joy.
entity = datastore.Entity(key)
entity['blob_name'] = blob.name
entity['image_public_url'] = blob.public_url
entity['timestamp'] = current_datetime
entity['joy'] = face_joy
# Save the new entity to Datastore.
datastore_client.put(entity)Storage 和 Vision 客户端库可以通过编程方式访问,方式与 Datastore 类似。您可以使用 vim、emacs 或 nano 自行打开 main.py 文件,以探索所有示例代码。
如需详细了解 Flask,请访问 http://flask.pocoo.org/。
如需详细了解客户端库,请访问 https://googlecloudplatform.github.io/google-cloud-python/。
homepage.html
Flask Web 框架利用 Jinja2 作为模板引擎。这样一来,我们便可将 main.py 中的变量和表达式传递到 homepage.html 中,这些变量和表达式在网页呈现后会被替换为相应的值。
如需详细了解 Jinja2,请访问 http://jinja.pocoo.org/docs/2.9/templates/。
此 Jinja2 HTML 模板显示了一个表单,供用户向数据库提交照片。此外,它还会显示之前提交的每张图片及其文件名、上传日期/时间和 Vision API 检测到的人脸表现出快乐情绪的可能性。
homepage.html
<h1>Google Cloud Platform - Face Detection Sample</h1>
<p>This Python Flask application demonstrates App Engine Flexible, Google Cloud
Storage, Datastore, and the Cloud Vision API.</p>
<br>
<html>
<body>
<form action="upload_photo" method="POST" enctype="multipart/form-data">
Upload File: <input type="file" name="file"><br>
<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>App Engine 柔性环境使用名为 app.yaml 的文件来描述应用的部署配置。如果该文件不存在,App Engine 会尝试推测部署配置。不过,建议您最好提供该文件。
接下来,您将使用自己选择的编辑器(vim、nano 或 emacs)修改 app.yaml。我们将使用 nano 编辑器:
nano app.yamlapp.yaml
runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app
runtime_config:
python_version: 3
env_variables:
CLOUD_STORAGE_BUCKET: <your-cloud-storage-bucket>这是部署 Python 3 App Engine 柔性应用所需的基本配置。您可以点击此处详细了解如何配置 App Engine。
打开 app.yaml 后,将 < your-cloud-storage-bucket > 替换为您的 Cloud Storage 存储分区的名称。(如果您忘记了 Cloud Storage 存储分区的名称,请从 Qwiklabs 中复制 GCP 项目 ID,该 ID 与存储分区名称相同)。env_variables 部分用于设置在应用部署后将在 main.py 中使用的环境变量。
现在,您可以使用 (Ctrl + x) 在 nano 中保存并关闭文件,系统会提示:

输入字母 y,然后再次按 ENTER 键,确认以下提示中的文件名:

使用 gcloud 在 App Engine 上部署应用:
gcloud app deploy部署应用后,您可以在网络浏览器中打开网址 https://< PROJECT_ID >.appspot.com 来访问该应用。
摘要
在此步骤中,您设置了一个 Python Web 应用并将其部署到了 App Engine 柔性环境。
您已了解如何编写和部署您的第一个 App Engine 柔性 Web 应用!
清理
为避免系统因本快速入门中使用的资源向您的 Google Cloud Platform 账号收取费用,请执行以下操作:
- 访问 Cloud Platform Console。
- 选择要关停的项目,然后点击顶部的“删除”:系统会安排删除该项目。
了解详情
- Google Cloud Platform 上的 Python:https://cloud.google.com/python/
- App Engine 柔性环境 Python 文档:https://cloud.google.com/appengine/docs/flexible/python/
- Python 客户端库文档:Datastore、Storage 和 Vision
- 更多 Python 代码示例:https://cloud.google.com/python/samples
许可
此作品已获得 Creative Commons Attribution 2.0 通用许可授权。