Cloud Storage に対する読み取りと書き込み

このドキュメントでは、Cloud Storage 用 App Engine クライアント ライブラリを使用して、App Engine アプリの Cloud Storage でデータの保存と取得を行う方法について説明します。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)

サンプルでは、書き込むファイルを開く呼び出しの中で、ファイルのカスタム メタデータを書き込む特定の Cloud Storage ヘッダーが指定されています。このメタデータは cloudstorage.stat() を使用して取得可能です。サポートされているヘッダーのリストは、cloudstorage.open() リファレンスをご覧ください。

x-goog-acl ヘッダーが設定されていないことにも注意してください。つまり、オブジェクトがバケットに書き込まれるとき、デフォルトの Cloud Storage ACL の public read がそのオブジェクトに適用されます。

最後に、書き込みが完了した後にファイルを閉じる close が呼び出されます。これを行わないと、ファイルは Cloud Storage に書き込まれません。Python ファイル関数 close() を呼び出した後は、ファイルに内容を追加できないことに注意してください。ファイルを変更する必要がある場合は、Python のファイル関数 open() を呼び出して、書き込みモードでファイルを再び開く必要があります。この場合は、追加ではなく上書きが行われます。

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)

選択した行をファイルから読み取るには、seek() を使用します。

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

  gcs_file = gcs.open(filename)
  self.response.write(gcs_file.readline())
  gcs_file.seek(-1024, os.SEEK_END)
  self.response.write(gcs_file.read())
  gcs_file.close()

どちらの例でも、cloudstorage.open() に渡す filename 引数は YOUR_BUCKET_NAME/PATH_IN_GCS 形式のファイルへのパスです。cloudstorage.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 に書き込むセクションでバケットに書き込んだファイルをクリーンアップしています。

次のステップ