App Engine 和 Google Cloud Storage 示例

区域 ID

REGION_ID 是 Google 根据您在创建应用时选择的地区分配的缩写代码。此代码不对应于国家/地区或省,尽管某些地区 ID 可能类似于常用国家/地区代码和省代码。对于 2020 年 2 月以后创建的应用,REGION_ID.r 包含在 App Engine 网址中。对于在此日期之前创建的现有应用,网址中的区域 ID 是可选的。详细了解地区 ID

了解如何启用 App Engine Python 应用的 Cloud Storage 访问权限,以及如何在 Cloud Storage 存储桶中创建、写入、读取和列出文件。

本教程假设您熟悉 Python 并已设置开发环境

当此示例运行时,会执行脚本并将输出写入浏览器。该脚本演示了 Cloud Storage 客户端库的以下功能:

  • 创建文件并将文件写入存储桶。
  • 读取文件并获取其文件元数据。
  • 创建多个文件,然后从存储桶中列出这些文件。
  • 列出刚刚添加到存储桶的文件。
  • 读取同一组文件。
  • 删除这组文件。

目标

  • 浏览 Python 项目以查看所需的布局和文件。
  • 了解用于连接到 Cloud Storage 的代码。
  • 了解用于创建、写入、读取、列出和删除文件的代码。
  • 了解用于重试的代码。
  • 在本地开发服务器中构建和测试应用。
  • 在 Google App Engine 上将应用部署到生产环境。

费用

App Engine 提供免费使用级别。如果 App Engine 的总使用量低于 App Engine 免费配额中指定的限制,则无需为执行本教程付费。

准备工作

在运行此示例之前,您需要项目 ID、gcloud 命令行工具和 Cloud Storage 存储分区:

  1. 创建一个新的 Google Cloud 控制台项目,或从 Google Cloud 控制台中检索现有项目的 ID:

    转到“项目”页面

  2. 安装并初始化 Google Cloud CLI:

    下载 SDK

  3. 激活默认的 Cloud Storage 存储分区

克隆教程项目

要克隆项目,请执行以下操作:

  1. 将客户端库和示例(演示)应用克隆到本地机器。

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples
    

    或者,您也可以下载该示例的 zip 文件并将其解压缩。

  2. 导航到已克隆或已下载项目中的相应目录:

    cd python-docs-samples/appengine/standard/storage/appengine-client
    

安装依赖项

借助 virtualenv 工具,您可以在系统中创建干净的 Python 环境。 对于 App Engine 开发,这有助于确保您在本地测试的代码,类似于您将在其中部署您的代码的环境。如需了解详情,请参阅使用第三方库

如需安装 virtualenv 和相应示例的依赖项,请执行以下操作:

Mac OS/Linux

  1. 如果您没有 virtualenv,请使用 pip 在系统范围内安装该工具:
    sudo pip install virtualenv
  2. 创建一个独立的 Python 环境
    virtualenv env
    source env/bin/activate
  3. 如果您当前不在包含示例代码的目录中,则导航到包含 hello_world 示例代码的目录。然后安装依赖项:
    cd YOUR_SAMPLE_CODE_DIR
    pip install -t lib -r requirements.txt

Windows

如果您已安装 Google Cloud CLI,则应该已经安装了 Python 2.7,通常位于 C:\python27_x64\ 中(适用于 64 位系统)。使用 Powershell 运行 Python 包。

  1. 找到已安装的 Powershell
  2. 右键点击 Powershell 的快捷方式,并以管理员身份启动。
  3. 尝试运行 python 命令。如果未找到,请将 Python 文件夹添加到环境的 PATH
    $env:Path += ";C:\python27_x64\"
  4. 如果您没有 virtualenv,请使用 pip 在系统范围内安装该工具:
    python -m pip install virtualenv
  5. 创建一个独立的 Python 环境
    python -m virtualenv env
    . env\Scripts\activate
  6. 导航到项目目录并安装依赖项。如果您当前不在包含示例代码的目录中,则导航到包含 hello_world 示例代码的目录。然后安装依赖项:
    cd YOUR_SAMPLE_CODE_DIR
    python -m pip install -t lib -r requirements.txt

您克隆或下载的示例代码已包含 appengine_config.py 文件,需要该文件才能指示 App Engine 使用 lib 文件夹在本地以及在部署时加载相关依赖项。

在本地运行

如需在本地运行示例,请执行以下操作:

  1. 在项目子目录 python-docs-samples/appengine/standard/storage/appengine-client 下,在本地开发服务器中运行应用:

    python3 CLOUD_SDK_ROOT/bin/dev_appserver.py .
    
  2. 等待系统返回如下所示的成功消息:

    INFO     2016-04-12 21:33:35,446 api_server.py:205] Starting API server at: http://localhost:36884
    INFO     2016-04-12 21:33:35,449 dispatcher.py:197] Starting module "default" running at: http://localhost:8080
    INFO     2016-04-12 21:33:35,449 admin_server.py:116] Starting admin server at: http://localhost:8000
    
  3. 在浏览器中访问以下网址:

    http://localhost:8080/

    应用将在网页加载时执行,并向浏览器显示输出以指明它已执行的内容。输出如下所示:

    Hello_Storage

  4. Control-C 停止开发服务器。

app.yaml 演示

app.yaml 文件指定了应用配置详细信息:

runtime: python27
api_version: 1
threadsafe: yes

env_variables:

handlers:
- url: /blobstore.*
  script: blobstore.app

- url: /.*
  script: main.app

要详细了解此文件中可用的配置选项,请参阅 app.yaml 参考

导入演示

main.py 文件包含用于通过客户端库访问 Cloud Storage 的典型导入项:

import os

import cloudstorage
from google.appengine.api import app_identity

import webapp2

您需要 os 模块和 app_identity API 才能在运行时获取默认存储桶名称。所有 Cloud Storage 访问操作都需要此存储桶名称。

该示例还使用 webapp2 Web 框架。

指定 Cloud Storage 存储桶

在 Cloud Storage 中执行任何操作之前,您需要提供存储桶名称。最简单的方法是使用项目的默认存储桶(可以按如下方式获取):

def get(self):
    bucket_name = os.environ.get(
        'BUCKET_NAME', app_identity.get_default_gcs_bucket_name())

    self.response.headers['Content-Type'] = 'text/plain'
    self.response.write(
        'Demo GCS Application running from Version: {}\n'.format(
            os.environ['CURRENT_VERSION_ID']))
    self.response.write('Using bucket name: {}\n\n'.format(bucket_name))

将文件写入 Cloud Storage

以下示例介绍如何写入存储桶:

def create_file(self, filename):
    """Create a file."""

    self.response.write('Creating file {}\n'.format(filename))

    # The retry_params specified in the open call will override the default
    # retry params for this particular file handle.
    write_retry_params = cloudstorage.RetryParams(backoff_factor=1.1)
    with cloudstorage.open(
        filename, 'w', content_type='text/plain', options={
            'x-goog-meta-foo': 'foo', 'x-goog-meta-bar': 'bar'},
            retry_params=write_retry_params) as cloudstorage_file:
                cloudstorage_file.write('abcde\n')
                cloudstorage_file.write('f'*1024*4 + '\n')
    self.tmp_filenames_to_clean_up.append(filename)

请注意,在调用 open 以打开文件进行写入时,该示例会指定特定 Cloud Storage 标头来写入该文件的自定义元数据;可以使用 cloudstorage.stat 检索此元数据。您可以在 cloudstorage.open 参考文档中找到受支持的标头列表。

另请注意,未设置 x-goog-acl 标头。这意味着,公共读取的默认 Cloud Storage ACL 将在写入存储桶时应用于该对象。

最后,请注意在完成写入后,应调用 close 以关闭文件。否则,不会将该文件写入 Cloud Storage。请注意,调用 close 后,您无法再对文件执行附加操作。如果您需要修改文件,则必须在写入模式下再次打开该文件,但这执行的是覆盖操作而不是附加操作。

从 Cloud Storage 读取文件

以下示例演示了如何从存储桶读取文件:

def read_file(self, filename):
    self.response.write(
        'Abbreviated file content (first line and last 1K):\n')

    with cloudstorage.open(filename) as cloudstorage_file:
        self.response.write(cloudstorage_file.readline())
        cloudstorage_file.seek(-1024, os.SEEK_END)
        self.response.write(cloudstorage_file.read())

该示例演示了如何使用 seek 显示正在读取的文件中的选定行,在本例中,这些行是打开的行和最后 1000 行。

请注意,上述代码未在打开文件进行读取时指定任何模式。open 的默认值是只读模式。

列出存储桶内容

该示例代码演示了如何使用 markermax_keys 参数浏览包含大量文件的存储桶,即浏览存储桶的内容列表:

def list_bucket(self, bucket):
    """Create several files and paginate through them."""

    self.response.write('Listbucket result:\n')

    # Production apps should set page_size to a practical value.
    page_size = 1
    stats = cloudstorage.listbucket(bucket + '/foo', max_keys=page_size)
    while True:
        count = 0
        for stat in stats:
            count += 1
            self.response.write(repr(stat))
            self.response.write('\n')

        if count != page_size or count == 0:
            break
        stats = cloudstorage.listbucket(
            bucket + '/foo', max_keys=page_size, marker=stat.filename)

请注意,完整的文件名显示为一个不含目录分隔符的字符串。如果要显示该文件,让其目录层次结构更易识别,请将 delimiter 参数设置为要使用的目录分隔符。

删除文件

该代码示例介绍文件删除操作,在这里,就是删除在应用执行期间添加的所有文件。您不需要在代码中执行此操作,因为这只是此示例的清理功能:

def delete_files(self):
    self.response.write('Deleting files...\n')
    for filename in self.tmp_filenames_to_clean_up:
        self.response.write('Deleting file {}\n'.format(filename))
        try:
            cloudstorage.delete(filename)
        except cloudstorage.NotFoundError:
            pass

部署示例

如需在 App Engine 上部署和运行该示例,请执行以下操作:

  1. 通过在 app.yaml 文件所在的 python-docs-samples/appengine/standard/storage/appengine-client 目录中运行以下命令,上传示例应用:

    gcloud app deploy
    

    可选标志:

    • 添加 --project 标志,可以为您在 gcloud CLI 中初始化为默认值的 Google Cloud 控制台项目 ID 指定一个备用项目 ID。示例:--project [YOUR_PROJECT_ID]
    • 添加 -v 标志以指定版本 ID。如果不指定,系统会为您生成一个版本 ID。示例:-v [YOUR_VERSION_ID]
  2. 部署过程完成后,您可以运行以下命令在 https://PROJECT_ID.REGION_ID.r.appspot.com 查看该应用:

    gcloud app browse
    

    demo 应用在网页加载时执行,就像在本地运行该应用时一样。但是,该应用现在会对 Cloud Storage 存储桶进行实际读写。

要详细了解如何从命令行部署应用,请参阅部署 Python 2 应用

后续步骤