6

The following line in my Google App Engine app (webapp.py) fails to import the Google Cloud library:

from google.cloud import storage

With the following error:

ImportError: No module named google.cloud.storage

I did some research and found the following articles to be helpful:

Using a combination of the techniques suggested by the above articles, I did the following:

  1. Create a requirements.txt file:

    google-cloud==0.19.0
    
  2. Import this library using pip:

    pip install -t lib -r requirements.txt
    
  3. Use the following code in my appengine_config.py file:

    import os
    import sys
    import google
    libDir = os.path.join(os.path.dirname(__file__), "lib")
    google.__path__.append(os.path.join(libDir, "google"))
    sys.path.insert(0, libDir)
    

Can anyone shed light on what I might be missing to get this working? I'm just trying to write a Google App Engine app that can write/read from Google Cloud Storage, and I'd like to test locally before deploying.

Community
  • 1
  • 1
nefaurk
  • 83
  • 1
  • 5

6 Answers6

6

It looks like the only thing that is required is to include google-cloud into your project requirements.txt file.

Check if this simple sample works for you (you shouldn't get any imports error). Create below files and run pip install -r requirements.txt -t lib. Nothing more is required on my site to make it work.

app.yaml

application: mysample
runtime: python27
api_version: 1
threadsafe: true

handlers:
  - url: /.*
    script: main.app

main.py

import webapp2
from google.cloud import storage


class MainPage(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.write('Hello, World!')

app = webapp2.WSGIApplication([
    ('/', MainPage),
], debug=True)

appengine_config.py

from google.appengine.ext import vendor
import os

# Third-party libraries are stored in "lib", vendoring will make
# sure that they are importable by the application.
if os.path.isdir(os.path.join(os.getcwd(), 'lib')):
    vendor.add('lib')

requirements.txt

google-cloud
manRo
  • 1,455
  • 1
  • 14
  • 19
  • Tried your suggestion in a test project, but got the same error: `ImportError: No module named google.cloud.storage` – nefaurk Oct 02 '16 at 16:54
  • are you starting dev server by running `dev_appserver.py` or `GoogleAppEngineLauncher` ? – manRo Oct 02 '16 at 18:16
3

There is an App Engine specific Google Cloud Storage API that ships with the App Engine SDK that you can use to work with Cloud Storage buckets.

import cloudstorage as gcs

Is there a reason you didn't use this built-in library, which requires no configuration to load?

BrettJ
  • 6,801
  • 1
  • 23
  • 26
  • 1
    I tried that after atimothee's 2nd suggestion and it worked! It wasn't clear to me that I should be using one over the other. – nefaurk Oct 02 '16 at 16:56
  • The fact that there are two libraries is rather confusing. Trying to search for one of them while excluding the other is pretty hard, but afaik `cloudstorage` does not support resumable uploads, while `google.cloud.storage` does. – Evert Heylen Mar 16 '17 at 20:29
1

Your appengine_config.py only needs to contain:

from google.appengine.ext import vendor
vendor.add('lib')

All the rest you have posted looks fine to me.

dyeray
  • 1,056
  • 6
  • 17
  • Thanks for the suggestion, dyeray! I tried replacing the contents of the `appengine_config.py` file with that and I'm still getting the same error. Any other ideas? – nefaurk Sep 26 '16 at 20:09
  • I don't know where the problem is then. It works for me by using above code with a fairly standard project with the latest version of Google Cloud SDK and deploying with *gcloud app deploy --project=*. Maybe there is something else going on in your project? – dyeray Sep 26 '16 at 20:15
  • Oh! I'm attempting to run my app locally using `dev_appserver.py`. Does that work for you on your project? – nefaurk Sep 26 '16 at 20:36
  • Sorry, I misread your message. I tried my code locally, but I hit yet another bug on the loval dev environment: https://github.com/google/oauth2client/issues/578. I don't think these guys are doing a good job at keeping the new generation libraries compatible with the local devserver. Maybe using the Google API Client libraries is an alternative? – dyeray Sep 27 '16 at 20:07
1

The package namespace seems to have been changed as pointed out in this github issue and hasn't been fully fixed. You could install the older version (pip install gcloud) which uses a different namespace & use this import statement instead:

from gcloud import storage

You should also ensure that you're importing vendor libs in your appengine_config.py as pointed out in dyeray's answer.

The issue seems to have been fixed as at version 0.20.0 of google-cloud. So the import statement in the question should work. Just remember to run pip install --upgrade google-cloud

atimothee
  • 658
  • 4
  • 11
  • If you're only interested in Cloud storage on appengine, you could just use the appengine Google cloud storage client lib https://cloud.google.com/appengine/docs/python/googlecloudstorageclient/setting-up-cloud-storage – atimothee Sep 27 '16 at 13:19
  • The above import statement didn't work, either. Now I'm getting: `ImportError: No module named gcloud` – nefaurk Oct 01 '16 at 14:06
  • Looks like the Google Cloud Storage Client Library ended up working for me—thanks, atimothee! – nefaurk Oct 02 '16 at 16:38
0

you should move "import google" line to the position after sys.path.insert

0

I've run into the same problem and took a long time to sort it out.

Setup 1: If your app.yaml is set up like below:

runtime: python27
api_version: 1
threadsafe: no

handlers:
- url: /.*
  script: main.app

libraries:
- name: jinja2
  version: "2.6"
- name: markupsafe
  version: "0.15

And your main.py is registered your script as an app:

from flask import Flask
app = Flask(__name__)
app.config['DEBUG'] = True

@app.route('/')
def hello():
    """Return a friendly HTTP greeting."""
    return 'Hello World!'

You should be able to run just fine on the google cloud.

Setup 2: How I ran into the ImportModule error -
In my app.yaml file I replaced script=main.app with script=main.app and deleted the

from flask import Flask
app = Flask(__name__)
app.config['DEBUG'] = True

from main.py file. As a result, appengine_config.py isn't getting run for setting the sys path. The solution is that you can either follow the pattern like Setup 1 or add the followings to your main.py file.

from google.appengine.ext import vendor
vendor.add('lib')

Then the app should have the right path for importing the third-party packages. Hope it helps.

Lily
  • 637
  • 2
  • 7
  • 16