App Engine と Google Cloud Storage のサンプル

リージョン ID

REGION_ID は、アプリの作成時に選択したリージョンに基づいて Google が割り当てる省略形のコードです。一部のリージョン ID は、一般的に使用されている国や州のコードと類似しているように見える場合がありますが、このコードは国または州に対応するものではありません。2020 年 2 月以降に作成されたアプリの場合、REGION_ID.r が App Engine の URL に含まれています。この日付より前に作成されたアプリの場合、URL のリージョン 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 コンソールから既存のプロジェクトのプロジェクト ID を取得します。

    プロジェクト ページに移動

    ヒント: gcloud コマンドライン ツールで既存のプロジェクト 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 へのショートカットを右クリックし、管理者として PowerShell を起動します。
  3. python コマンドを実行してみます。見つからない場合は、環境の PATH に Python フォルダを追加します。
    $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 ファイルが含まれています。これは、ローカルとデプロイ時の両方で依存関係をロードする際に lib フォルダを使用するように App Engine に指示するために必要です。

ローカルでの実行

サンプルをローカルで実行するには、次のようにします。

  1. プロジェクト サブディレクトリ python-docs-samples/appengine/standard/storage/appengine-client に移動し、[local development server] でアプリを実行します。

    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. ブラウザで、次の URL にアクセスします。

    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 ウェブ フレームワークも使用しています。

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 の public read がそのオブジェクトに適用されます。

最後に、書き込みが完了した後にファイルを閉じる 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 を使用して、開始行と最後の 1,000 行を表示します。

上記のコードでは、ファイルを読み取り用に開く際に、モードを指定していないことに注意してください。open のデフォルトは読み取り専用モードです。

バケットの内容を一覧表示する

このサンプルコードでは、バケットの内容の一覧をページ処理するための marker パラメータと max_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)

完全なファイル名が、ディレクトリ区切り記号なしで 1 つの文字列として表示されていることに注意してください。わかりやすいディレクトリ階層でファイルを表示させる場合は、使用するディレクトリ区切り記号を 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
    

    オプションのフラグ:

    • gcloud CLI でデフォルトとして初期設定したものに代わるコンソール プロジェクト ID を指定するには、--project フラグを指定します。例: --project [YOUR_PROJECT_ID]
    • -v フラグを含めると、バージョン 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 アプリをデプロイするをご覧ください。

次のステップ