Python 2 不再受社区支持。我们建议您将 Python 2 应用迁移到 Python 3

App Engine 和 Google Cloud Storage 示例

区域 ID

REGION_ID 是 Google 根据您在创建应用时选择的区域分配的缩写代码。此代码不对应于国家/地区或省,尽管某些区域 ID 可能类似于常用国家/地区代码和省代码。在 App Engine 网址中包含 REGION_ID.r 对于现有应用是可选的,这将很快成为对所有新应用的要求。为了确保顺利过渡,我们正在逐步更新 App Engine 以使用区域 ID。如果我们尚未更新您的 Google Cloud 项目,则您不会看到应用的区域 ID。由于该 ID 对于现有应用是可选的,因此您在现有应用可以使用区域 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. 新建一个 Cloud Console 项目,或从 Google Cloud Console 中检索现有项目的项目 ID:

    转到“项目”页面

    提示:使用 gcloud 命令行工具检索现有项目 ID 的列表。

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

    下载 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. 导航到项目目录并安装依赖项:
    cd YOUR_PROJECT
    pip install -t lib -r requirements.txt

Windows

如果您已安装 Cloud SDK,则应该已经安装了 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. 导航到项目目录并安装依赖项:
    cd YOUR_PROJECT
    python -m pip install -t lib -r requirements.txt

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

在本地运行

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

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

    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 标志,指定一个其他项目 ID(不同于您在 gcloud 工具中初始化为默认值的 Cloud Console 项目 ID)。示例:--project [YOUR_PROJECT_ID]
    • 添加 -v 标志以指定版本 ID。如果不指定,系统会为您生成一个版本 ID。示例:-v [YOUR_VERSION_ID]

    提示:如果指定先前上传的应用的版本 ID,则部署将覆盖 App Engine 上的现有版本。 这并非总是可取的,特别是在 App Engine 上的版本正在处理流量时。为了避免中断应用的流量,您可以使用不同的版本 ID 部署应用,然后将流量移至该版本。要详细了解如何移动流量,请参阅流量拆分

  2. 部署过程完成后,您可以运行以下命令在 https://PROJECT_ID.REGION_ID.r.appspot.com 查看该应用:

    gcloud app browse
    

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

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

后续步骤