Python 2 は、コミュニティによるサポートを終了しました。Python 2 アプリを Python 3 に移行することをおすすめします。

Google Cloud Storage の読み取りと書き込み

このドキュメントでは、Cloud Storage 用 App Engine クライアント ライブラリを使用して、App Engine アプリの Cloud Storage でデータの保存と取得を行う方法について説明します。先に Google Cloud Storage の設定で説明されているように、Cloud Storage バケットを有効にし、クライアント ライブラリをダウンロードしておく必要があります。また、Python 2 App Engine スタンダード環境のクイックスタートで説明されている、App Engine アプリケーションのビルド方法を理解している必要があります。

必要なインポート

main.py ファイルには、クライアント ライブラリを介して Cloud Storage にアクセスするために使用される標準的なインポートが含まれています。

import logging
import os
import cloudstorage as gcs
import webapp2

from google.appengine.api import app_identity

実行時にデフォルト バケット名を取得するには、os モジュールと app_identity API が必要です。デフォルトのバケットを使用しない場合には、別の方法でバケット名を渡す必要があります。

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: '
                      + os.environ['CURRENT_VERSION_ID'] + '\n')
  self.response.write('Using bucket name: ' + bucket_name + '\n\n')

get_default_gcs_bucket_name の呼び出しは、プロジェクトにデフォルト バケットを作成した場合にのみ成功します。

Cloud Storage に書き込む

次のサンプルは、バケットに書き込む方法を示しています。

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

  The retry_params specified in the open call will override the default
  retry params for this particular file handle.

  Args:
    filename: filename.
  """
  self.response.write('Creating file %s\n' % filename)

  write_retry_params = gcs.RetryParams(backoff_factor=1.1)
  gcs_file = gcs.open(filename,
                      'w',
                      content_type='text/plain',
                      options={'x-goog-meta-foo': 'foo',
                               'x-goog-meta-bar': 'bar'},
                      retry_params=write_retry_params)
  gcs_file.write('abcde\n')
  gcs_file.write('f'*1024*4 + '\n')
  gcs_file.close()
  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('Reading the full file contents:\n')

  gcs_file = gcs.open(filename)
  contents = gcs_file.read()
  gcs_file.close()
  self.response.write(contents)

filename 引数は、YOUR_BUCKET_NAME/PATH_IN_GCS の形式で指定します。このサンプルでは、読み取り対象のファイルから選択した行を表示する方法が示されています。サンプルでは seek を使用して、開始行と最後の 1,000 行を表示します。

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

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

このサンプルコードでは、バケットの内容の一覧をページ処理するための marker パラメータと max_keys パラメータを使用して、多数のファイルを含むバケットをページ処理するための方法を示しています。

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

  Production apps should set page_size to a practical value.

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

  page_size = 1
  stats = gcs.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 = gcs.listbucket(bucket + '/foo', max_keys=page_size,
                           marker=stat.filename)

完全なファイル名が、ディレクトリ区切り記号なしで 1 つの文字列として表示されていることに注意してください。わかりやすいディレクトリ階層でファイルを表示させる場合は、使用するディレクトリ区切り記号を delimiter パラメータに設定します。

Cloud Storage のファイルを削除する

次のコードは、cloudstorage.delete() メソッド(gcs としてインポート)を使用して Cloud Storage からファイルを削除する方法を示しています。

def delete_files(self):
  self.response.write('Deleting files...\n')
  for filename in self.tmp_filenames_to_clean_up:
    self.response.write('Deleting file %s\n' % filename)
    try:
      gcs.delete(filename)
    except gcs.NotFoundError:
      pass

この例では、Cloud Storage に書き込むセクションでバケットに書き込んだファイルをクリーンアップしています。

次のステップ