在过去的几天里(在我可以花在这个项目上的奇怪时间里),我一直在努力开始使用 Google Drive API 和 GAE python 中的服务帐户进行本地调试。
我的设置:
- 日食 4.4
- 适用于 Python 1.8.0 的 Google App Engine SDK
- 谷歌 API 客户端 Python GAE 1.1
我已经在 app.yaml 中激活了(除其他外)这些 3rd 方库:
- name: pycrypto
version: latest
- name: ssl
version: latest
到目前为止,这是我对设置的理解,有几个陈述:
- 因为我的应用不需要访问用户文件,而是特定于应用的文件,所以应用应该使用“服务帐户”来拥有和访问 Google Drive 上的文件
- 服务帐户可以通过两种方式进行身份验证:(1) 通过 API 密钥和 (2) 通过私钥凭证
- 使用 SDK 开发 GAE 应用程序时,需要考虑两个环境:本地系统(用于调试)和 GAE 服务器(用于部署)
- 在本地系统上运行时,API 密钥身份验证不起作用(并且永远不会起作用),因为是两条腿的身份验证(不要完全掌握这个......,但它似乎是真的)
很想要本地调试工具,因为我是学python,学google驱动接口,所以在服务器上调试是个很大的负担。
所以我需要让私钥凭证在本地系统上工作。但后来我遇到了问题“ImportError:无法导入名称 SignedJwtAssertionCredentials”。尝试了我在网上找到的几乎所有东西:
- 使用 python 2.7 运行时并启用 pycrypto 库
- 将 google-api-python-client-gae 升级到 1.1(包括此修复)
- 在我的系统上安装了 OpenSSL(但可能没有成功设置正确的路径)
- 阅读说明以在本地安装 pycrypto,但假设它们已过时
=>我的第一个问题,只是为了理解,是:是否有可能在本地系统上使用 Python 从 GAE SDK 到 Google Drive API 进行身份验证?也许答案很简单“不”?
=> 如果答案是“是”,那么是否会有示例设置和代码示例来展示实现此本地身份验证的方法?
=> 错误日志(如下)似乎表明 pycrypto 不可用仍然存在问题,但文档非常明确地说它包含在 Python 2.7 GAE 运行时环境中。
=>也许(请确认)我对本地和服务器python设置之间的区别感到困惑。当我在 Eclipse 中查看“运行本地”PYTHONPATH 时,它包括(1)我的项目文件夹,(2)google-api-client-python-gae 文件夹(似乎不包括 pycrypto !!),而GAE 运行时 --- 有什么区别?(3) 我的本地 Python 2.7 部署。那么这个本地配置中缺少什么我需要模仿服务器配置才能开始调试?
这是我使用私钥凭据进行身份验证的代码:
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)
这是我的错误日志:
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.
[更新] 回顾我的问题,我想我需要仔细研究在本地安装 pycrypto。如果这是解决方法,我将就这篇文章提供反馈中提供反馈,以请求添加有关 GAE 服务器运行时库和本地 SDK 库之间差异的注释。我也会在这里添加安装说明。
[update2] SignedJwtAssertionCredentials 导入问题已经解决,但是 tlslite 包上出现了另一个导入问题。我不知道如何解决这个问题,因为导入看起来非常正常,我求助于从头开始重新配置整个 IDE。我现在安装了另一个预编译的 pycrypto 库,并按照错误消息中的提示,将我的 .p12 私钥文件转换为 .pem 文件。请注意,openssl 创建的 .pem 文件在“-----BEGIN”之前包含 4 个文本行,我必须手动删除这些文本行才能使 .pem 文件被 oauth2client 识别!
[update3] 从头开始重新配置 IDE 时,我忽略了使用“old_dev_appserver.py”在本地运行应用程序,而不是“dev_appserver.py”。后者不会启用断点!但它看起来与 SignedJwtAssertionCredentials 导入问题有关。使用“dev_appserver.py”,我没有导入问题(但没有断点),使用“old_dev_appserver.py”,我可以重现导入问题。所以'old_dev_appserver.py'可能一直是问题的一部分!