Before running through the steps below, make sure that:
- You have activated your project for GCS and App Engine, including creating at least one GCS bucket.
- You have downloaded the client lib distribution and unzipped it.
- You have installed the App Engine SDK. (We need to use its
appcfg.pytool to upload the demo to App Engine.)
Deploying and Running the Sample
To deploy and run the /demo sample:
- In your installation directory of the client library, open
demo/main.py. - Under the class
MainPage, change the setting forbucket_name =to the name of your GCS bucket. You can leave all other values in their current settings. - Open
demo/app.yamland change theapplication:setting to your App Engine Application ID. - Upload the demo to your Cloud project by invoking
appcfg.py:/path/to/AppEngSDK/appcfg.py update /path/to/demo - Follow the prompts to supply email and password in order to upload the app.
- Wait until the app successfully uploads and deploys, then visit the App Engine console.
- Locate your app in the applications list and click on the
link labeled
Running. -
You should see something like this:

Understanding the Sample
The sample creates files, lists
bucket contents, and deletes the file. In the listbucket section, the code
sample shows how to use marker, and max_keys in regular mode to page through
a list of the contents of the bucket:
"""A sample app that uses GCS client to operate on bucket and file."""
import logging
import os
import cloudstorage as gcs
import webapp2
from google.appengine.api import app_identity
# Retry can help overcome transient urlfetch or GCS issues, such as timeouts.
my_default_retry_params = gcs.RetryParams(initial_delay=0.2,
max_delay=5.0,
backoff_factor=2,
max_retry_period=15)
# All requests to GCS using the GCS client within current GAE request and
# current thread will use this retry params as default. If a default is not
# set via this mechanism, the library's built-in default will be used.
# Any GCS client function can also be given a more specific retry params
# that overrides the default.
# Note: the built-in default is good enough for most cases. We override
# retry_params here only for demo purposes.
gcs.set_default_retry_params(my_default_retry_params)
class MainPage(webapp2.RequestHandler):
"""Main page for GCS demo application."""
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')
bucket = '/' + bucket_name
filename = bucket + '/demo-testfile'
self.tmp_filenames_to_clean_up = []
try:
self.create_file(filename)
self.response.write('\n\n')
self.read_file(filename)
self.response.write('\n\n')
self.stat_file(filename)
self.response.write('\n\n')
self.create_files_for_list_bucket(bucket)
self.response.write('\n\n')
self.list_bucket(bucket)
self.response.write('\n\n')
self.list_bucket_directory_mode(bucket)
self.response.write('\n\n')
except Exception, e: # pylint: disable=broad-except
logging.exception(e)
self.delete_files()
self.response.write('\n\nThere was an error running the demo! '
'Please check the logs for more details.\n')
else:
self.delete_files()
self.response.write('\n\nThe demo ran successfully!\n')
# When writing a file to Cloud Storage, you should not call finally:close() as
# this can result in finalizing object uploads even if there was an exception
# during a write.
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)
def read_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()
def stat_file(self, filename):
self.response.write('File stat:\n')
stat = gcs.stat(filename)
self.response.write(repr(stat))
def create_files_for_list_bucket(self, bucket):
self.response.write('Creating more files for listbucket...\n')
filenames = [bucket + n for n in ['/foo1', '/foo2', '/bar', '/bar/1',
'/bar/2', '/boo/']]
for f in filenames:
self.create_file(f)
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
# pylint: disable=undefined-loop-variable
stats = gcs.listbucket(bucket + '/foo', max_keys=page_size,
marker=stat.filename)
def list_bucket_directory_mode(self, bucket):
self.response.write('Listbucket directory mode result:\n')
for stat in gcs.listbucket(bucket + '/b', delimiter='/'):
self.response.write('%r' % stat)
self.response.write('\n')
if stat.is_dir:
for subdir_file in gcs.listbucket(stat.filename, delimiter='/'):
self.response.write(' %r' % subdir_file)
self.response.write('\n')
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
app = webapp2.WSGIApplication([('/', MainPage)],
debug=True)
The sample also shows how to use listbucket in directory mode using the
delimiter argument and the GCSFileStat
is_dir
instance property to list the contents of of a specified directory, along with
its subdirectories.
Finally, the sample shows you how to use
RetryParams to change default timeout and retry settings.
Notice that the x-goog-acl header is not set. That means the default GCS ACL
of public read is going to be applied to the object when it is written to GCS.