In Cloud Storage lesen und schreiben

In diesem Dokument wird beschrieben, wie Daten mithilfe von Cloud Storage in einer App Engine-Anwendung gespeichert und abgerufen werden. Dabei wird die App Engine-Clientbibliothek für Cloud Storage verwendet. Es wird davon ausgegangen, dass Sie die unter Cloud Storage einrichten beschriebenen Aufgaben durchgeführt und somit einen Cloud Storage-Bucket aktiviert sowie die Clientbibliotheken heruntergeladen haben. Außerdem wird angenommen, dass Sie eine App Engine-Anwendung erstellen können, wie es in der Kurzanleitung für Python 2 in einer App Engine-Standardumgebung erläutert wird.

Erforderliche Importe

Die Datei main.py enthält die typischen Importe für den Zugriff auf Cloud Storage über die Clientbibliothek:

import logging
import os
import cloudstorage as gcs
import webapp2

from google.appengine.api import app_identity

Sie benötigen das os-Modul und die app_identity API, um den Namen des Standard-Buckets zur Laufzeit abzurufen. Beachten Sie, dass Sie den Bucket-Namen auf andere Weise angeben müssen, wenn Sie den Standard-Bucket nicht verwenden.

Cloud Storage-Bucket angeben

Bevor Sie Vorgänge in Cloud Storage ausführen können, müssen Sie den Bucket-Namen angeben. Der einfachste Weg dafür ist die Verwendung des Standard-Buckets für Ihr Projekt. Diesen erhalten Sie folgendermaßen:

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')

Der Aufruf von get_default_gcs_bucket_name ist nur erfolgreich, wenn Sie den Standard-Bucket für Ihr Projekt erstellt haben.

Schreibvorgänge in Cloud Storage

Im folgenden Beispiel wird gezeigt, wie in den Bucket geschrieben wird:

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)

Beachten Sie Folgendes: Im Beispiel werden beim Aufrufen von für das Öffnen der Datei zum Schreiben bestimmte Cloud Storage-Header angegeben, die benutzerdefinierte Metadaten für die Datei festlegen. Diese Metadaten können mit cloudstorage.stat() abgerufen werden. Eine Liste der unterstützten Header finden Sie in der Referenz zu cloudstorage.open().

Beachten Sie auch, dass der Header x-goog-acl nicht festgelegt wird. Das bedeutet, dass beim Schreiben in den Bucket die standardmäßige Cloud Storage-ACL für öffentlichen Lesezugriff auf das Objekt angewendet wird.

Beachten Sie außerdem den Aufruf zum Schließen der Datei, nachdem der Schreibvorgang abgeschlossen ist. Ohne diesen Aufruf wird die Datei nicht in Cloud Storage geschrieben. Nach dem Aufrufen der Python-Dateifunktion close() können Sie die Datei nicht mehr anhängen. Wenn Sie eine Datei ändern möchten, müssen Sie die Python-Dateifunktion open() aufrufen, um die Datei im Schreibmodus noch einmal zu öffnen. Dadurch wird sie überschrieben und nicht angehängt.

Lesevorgänge in Cloud Storage

Im folgenden Beispiel wird gezeigt, wie eine Datei aus dem Bucket gelesen wird:

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)

Um ausgewählte Zeilen aus der Datei zu lesen, verwenden Sie 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()

In beiden Beispielen ist das Argument filename, das Sie an cloudstorage.open() übergeben, der Pfad zu Ihrer Datei im Format YOUR_BUCKET_NAME/PATH_IN_GCS. Beachten Sie, dass der Standardwert für cloudstorage.open() schreibgeschützt ist. Sie müssen beim Öffnen einer Datei für das Lesen keinen Modus angeben.

Bucket-Inhalt auflisten

Der Beispielcode zeigt, wie Sie mit den Parametern marker und max_keys einen Bucket mit einer großen Anzahl an Dateien durchgehen, um eine Liste der Inhalte des Buckets zu prüfen:

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)

Beachten Sie, dass der vollständige Dateiname als eine Zeichenfolge ohne Verzeichnistrennzeichen angezeigt wird. Wenn Sie die Datei mit der besser erkennbaren Verzeichnishierarchie darstellen möchten, legen Sie für den Parameter delimiter das gewünschte Verzeichnistrennzeichen fest.

Dateien in Cloud Storage löschen

Der folgende Code zeigt, wie Sie eine Datei aus Cloud Storage mit der Methode cloudstorage.delete() löschen (als gcs importiert).

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

In diesem Beispiel werden die Dateien bereinigt, die im Abschnitt Schreibvorgänge in Cloud Storage in den Bucket geschrieben wurden.

Weitere Informationen