Using the Google Drive API with a service account in a python project for Google Apps Engine with local debugging

over the last couple of days (during the odd hour that I can spend on this project), I struggled to start using the Google Drive API with a service account in python GAE for local debugging.

My setup:

  • Eclipse 4.4
  • Google App Engine SDK for Python 1.8.0
  • Google Python API Client GAE 1.1

I activated (among others) these third-party libraries in app.yaml:

- name: pycrypto version: latest - name: ssl version: latest 

This is what I understand about setting up sofar, in a few statements:

  • because my application doesn’t need to access user files, but the application-specific file, the application must use the “service account” to own and access the file in Google Drive.
  • service accounts can be authenticated in two ways: (1) an API key and (2) private key credentials
  • When developing a GAE application using the SDK, two environments must be considered: the local system (for debugging) and the GAE server (for deployment)
  • API key authentication does not work (and will never work) when launched on the local system due to two-way authentication (do not fully understand this ... but it seems true).

I really need a local debugging function because I am learning python and learning the interface of the Google interface, so debugging on the server is a big load.

Therefore, I need to get the secret key credentials running on the local system. But then I ran into the problem "ImportError: I can not import the name SignedJwtAssertionCredentials". Tried almost everything I found on the Internet:

  • using python 2.7 runtime and including pycrypto library
  • update google-api-python-client-gae to 1.1 (which includes this fix)
  • OpenSSL is installed on my system (but probably failed to set the correct paths)
  • read the installation instructions for pycrypto locally, but suggested they are outdated.

=> My first question is just to understand: is it even possible to authenticate your local system from SDE GAE to the Google Drive API using Python? Maybe the answer is very simple no.

=> if the answer is yes, then will there be an example example and code sample to show how to achieve this local authentication?

=> The error log (below) seems to indicate that there is still a problem with pycrypto inaccessibility, but the docs explicitly state that it is included in the Python 2.7 GAE runtime.

=> possible (please confirm). I am confused by the difference between local and server python configuration. When I look at Eclipse's “Run Local” PYTHONPATH, it includes (1) my project folders, (2) google-api-client-python-gae folders (which don't seem to include pycrypto !!), whereas GAE runtime - what's the difference? and (3) my local deployment of Python 2.7. So, what is missing in this local configuration, what do I need to emulate server configurations to start debugging?

This is my code for authentication using private key credentials:

 from oauth2client.client import SignedJwtAssertionCredentials f = file(SERVICE_ACCOUNT_PKCS12_FILE_PATH, 'rb') key = f.read() f.close() credentials = SignedJwtAssertionCredentials(SERVICE_ACCOUNT_EMAIL, key, scope=OAUTH_SCOPE) http = httplib2.Http() http = credentials.authorize(http) return build('drive', 'v2', http=http) 

This error log is:

 ERROR 2013-06-18 00:59:57,562 dev_appserver_import_hook.py:1251] Third party package Crypto was enabled in app.yaml but not found on import. You may have to download and install it. ERROR 2013-06-18 00:59:59,255 dev_appserver_import_hook.py:1251] Third party package Crypto was enabled in app.yaml but not found on import. You may have to download and install it. ERROR 2013-06-18 00:59:59,289 webapp2.py:1552] import_string() failed for 'illustrations.SyncHandler'. Possible reasons are: - missing __init__.py in a package; - package or module path not included in sys.path; - duplicated package or module name taking precedence in sys.path; - missing module, class, function or variable; Original exception: ImportError: cannot import name SignedJwtAssertionCredentials Debugged import: - 'illustrations' not found. Traceback (most recent call last): File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 1535, in __call__ rv = self.handle_exception(request, response, e) File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 1529, in __call__ rv = self.router.dispatch(request, response) File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 1272, in default_dispatcher self.handlers[handler] = handler = import_string(handler) File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 1850, in import_string return getattr(__import__(module, None, None, [obj]), obj) File "C:\Program Files (x86)\Google\google_appengine\google\appengine\tools\dev_appserver_import_hook.py", line 692, in Decorate return func(self, *args, **kwargs) File "C:\Program Files (x86)\Google\google_appengine\google\appengine\tools\dev_appserver_import_hook.py", line 1766, in load_module return self.FindAndLoadModule(submodule, fullname, search_path) File "C:\Program Files (x86)\Google\google_appengine\google\appengine\tools\dev_appserver_import_hook.py", line 692, in Decorate return func(self, *args, **kwargs) File "C:\Program Files (x86)\Google\google_appengine\google\appengine\tools\dev_appserver_import_hook.py", line 1630, in FindAndLoadModule description) File "C:\Program Files (x86)\Google\google_appengine\google\appengine\tools\dev_appserver_import_hook.py", line 692, in Decorate return func(self, *args, **kwargs) File "C:\Program Files (x86)\Google\google_appengine\google\appengine\tools\dev_appserver_import_hook.py", line 1577, in LoadModuleRestricted description) File "C:\Users\vic\Dropbox\Development\Eclipse-juno-workspace\Missale\src\illustrations.py", line 6, in <module> import drive File "C:\Program Files (x86)\Google\google_appengine\google\appengine\tools\dev_appserver_import_hook.py", line 692, in Decorate return func(self, *args, **kwargs) File "C:\Program Files (x86)\Google\google_appengine\google\appengine\tools\dev_appserver_import_hook.py", line 1766, in load_module return self.FindAndLoadModule(submodule, fullname, search_path) File "C:\Program Files (x86)\Google\google_appengine\google\appengine\tools\dev_appserver_import_hook.py", line 692, in Decorate return func(self, *args, **kwargs) File "C:\Program Files (x86)\Google\google_appengine\google\appengine\tools\dev_appserver_import_hook.py", line 1630, in FindAndLoadModule description) File "C:\Program Files (x86)\Google\google_appengine\google\appengine\tools\dev_appserver_import_hook.py", line 692, in Decorate return func(self, *args, **kwargs) File "C:\Program Files (x86)\Google\google_appengine\google\appengine\tools\dev_appserver_import_hook.py", line 1577, in LoadModuleRestricted description) File "C:\Users\vic\Dropbox\Development\Eclipse-juno-workspace\Missale\src\drive.py", line 6, in <module> from oauth2client.client import SignedJwtAssertionCredentials ImportStringError: import_string() failed for 'illustrations.SyncHandler'. Possible reasons are: - missing __init__.py in a package; - package or module path not included in sys.path; - duplicated package or module name taking precedence in sys.path; - missing module, class, function or variable; Original exception: ImportError: cannot import name SignedJwtAssertionCredentials Debugged import: - 'illustrations' not found. 

[update], considering my question, I think I will need to get a closer look at installing pycrypto locally. If this is a fix, I will send feedback on this article to request a note on inconsistencies between the GAE runtime libraries and the local SDK libraries. And I will also add installation instructions.

[update2] The import problem of SignedJwtAssertionCredentials has disappeared, but another import problem has appeared in the tlslite package. I had no idea how to fix this, because the import looked completely healthy, and I resorted to reconfiguring the entire IDE from scratch. I installed another pre-compiled pycrypto library and I followed the prompt in the error message and converted the private key file .p12 to the .pem file. Note that the .pem file created by openssl contained 4 lines of text before "----- BEGIN", which I had to delete manually so that the .pem file was recognized by oauth2client!

[update3] when reconfiguring the IDE from scratch, I missed the opportunity to use "old_dev_appserver.py" to run the application locally, rather than "dev_appserver.py". The latter will not turn on breakpoints! But it seems that this has something to do with the import problem of SignedJwtAssertionCredentials. Using "dev_appserver.py", I have no import problem (but no breakpoints) and using "old_dev_appserver.py", I can reproduce the import problem. Thus, "old_dev_appserver.py" can be part of the problem all the time!

+7
source share
1 answer

Yes - you can use SignedJwtAssertionCredentials to connect to Google services. I wrote code that does this in due time, and it works great. Using this class is one of the problems. The GAE provides the PyCrypto library, as you wrote, but you must install it manually on the local computer. GAE has its own modified version of this library, so they did not provide its source code. The second problem with this library is that it is compiled for the specified machine, which will use it. If you look in the source code of this class, you will see that it needs some dependencies to work. If they do not meet the requirements of this class, it will be unavailable from outside the code.

I cannot write anything about import problems in the old and new dev_server, because I know nothing about it.

+1
source

All Articles