如何在Mac OS X 10.6上使用virtualenv和Google App Engine SDK?

30

我正努力地摆脱这个问题,因为它在上周之前是可以工作的,但不知何故现在无法正常运行。

当我为Google App Engine应用程序设置虚拟环境并使用dev_appserver.py启动应用程序时,我出现了导入标准库时的错误(例如“ImportError: No module named base64”)。

以下是我的操作:

(使用系统Python)

virtualenv --python=python2.5 --no-site-packages ~/.virtualenv/foobar

然后,我将一个gae.pth文件添加到~/.virtualenv/foobar/lib/python2.5/site-packages/中,该文件包含Google App Engine库的信息:

/usr/local/google_appengine
/usr/local/google_appengine/lib/antlr3
/usr/local/google_appengine/lib/cacerts
/usr/local/google_appengine/lib/django
/usr/local/google_appengine/lib/fancy_urllib
/usr/local/google_appengine/lib/ipaddr
/usr/local/google_appengine/lib/webob_1_1_1
/usr/local/google_appengine/lib/yaml/lib

这是基于这个答案的。

然后我激活了我的 "foobar" 虚拟环境,并尝试使用 dev_appserver.py 启动应用程序。

服务器启动了,但第一次请求出现了前面提到的 "ImportError: No module named base64" 错误。如果我访问管理控制台,则会得到 "ImportError: No module named cgi"。

如果我启动 Python,我可以加载这些模块。

>>> import base64
>>> base64.__file__
'/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/base64.py'

似乎SDK的沙箱机制阻止了这些库的加载。但就像我之前所说的,直到上周我都可以使用这个功能...不知道发生了什么变化或者我不小心破坏了虚拟环境,我无法弄清楚我最初是如何使其工作的。

软件版本:

Google App Engine SDK 1.3.7
Mac OS X Snow Leopard 10.6.4
virtualenv 1.5.1

更新: 回答Alan Franzoni的问题:

我正在使用Mac OS X自带的系统Python。 我通过easy_install安装了virtualenv。 今天我升级到了virtualenv 1.5.1以尝试修复这个问题。

如果我使用虚拟环境python运行python /usr/local/bin/dev_appserver.py,问题仍然存在。 如果我取消激活虚拟环境并使用系统python2.5运行该命令,则可以正常工作。 (此外,我也可以使用GoogleAppEngineLauncher启动我的应用程序。)

这是完整的堆栈跟踪(此示例使用Kay框架,但使用webapp时问题相同):

Traceback (most recent call last):
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 3206, in _HandleRequest
    self._Dispatch(dispatcher, self.rfile, outfile, env_dict)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 3149, in _Dispatch
    base_env_dict=env_dict)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 525, in Dispatch
    base_env_dict=base_env_dict)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 2402, in Dispatch
    self._module_dict)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 2312, in ExecuteCGI
    reset_modules = exec_script(handler_path, cgi_path, hook)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 2208, in ExecuteOrImportScript
    exec module_code in script_module.__dict__
  File "/Users/look/myapp/kay/main.py", line 17, in <module>
    kay.setup()
  File "/Users/look/myapp/kay/__init__.py", line 122, in setup
    from google.appengine.ext import db
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 1287, in Decorate
    return func(self, *args, **kwargs)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 1937, in load_module
    return self.FindAndLoadModule(submodule, fullname, search_path)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 1287, in Decorate
    return func(self, *args, **kwargs)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 1839, in FindAndLoadModule
    description)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 1287, in Decorate
    return func(self, *args, **kwargs)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 1790, in LoadModuleRestricted
    description)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/db/__init__.py", line 81, in <module>
    import base64
ImportError: No module named base64

请问您能否将出错的完整输出复制粘贴一下?如果使用“python /usr/local/bin/dev_appserver.py”,错误是否仍然存在?另外,您是通过setuptools安装virtualenv的吗?您正在使用系统自带的python2.5、macports版本的python还是两者的组合? - Alan Franzoni
感谢您的回复。我已更新帖子以回答您的问题。 - Luke Francl
你可以输入“which python”来确保你正在运行 virtualenv Python 吗? - varikin
如果您在虚拟环境中运行Python交互式环境,是否可以成功导入“base64”模块?(我已经在OSX上使用GAE的svn主干源代码在虚拟环境中工作过了,而不是安装.dmg文件。如果需要,我可以将我的步骤发布为答案,但目前我只有helloworld教程应用程序,没有任何复杂的应用程序。) - snapshoe
SDK ≥ 1.6.1 + gae.pth 是在多虚拟环境设置中保持 SDK 同步的好方法。通过添加 setup.py + MANIFEST.in,我成功地使其可通过 pip 安装 = 100% 自动化,并使 SDK 在虚拟环境中运行,无需打补丁 - lukmdo
5个回答

15

这是关于Google应用引擎(GAE) SDK的4339号问题,已确认存在,并在错误记录中提供了两个略有不同的修补程序使其正常工作。

dev_appserver.py会通过计算os模块的位置来设置受限制的Python环境,以禁止访问任何非系统Python模块。在虚拟环境实例中,os.py被链接到虚拟环境中,但直接编译到虚拟环境中,而这就是dev_appserver使用的路径,有效地阻止访问大多数未由virtualend链接的系统Python库中的任何模块。解决方案是“祝福”这两个路径。


问题4339刚刚被标记为SDK版本1.6.1的已修复。我尝试了一下,现在它对我来说又可以工作了! - Luke Francl

2
Google AppEngine SDK在安装时采用了许多技巧来将其安装到sys.path中,这些技巧依赖于实际文件路径。我认为可能有很多原因导致它失败。SDK不会像一个真正的Python包一样安装自己,virtualenv也不能完全隔离,它只是设置了一个环境(显然)并更改了sys.path。GAE SDK也是如此,它们都会干扰,而且SDK正在快速发展和经常变化,所以这是一条非常崎岖的道路。
也许最好的方法是解释一下您想要实现什么。我猜测你试图创建一个干净的环境,以确保应用程序没有任何第三方模块可用。如果这个猜测是正确的,我建议通过requirements文件将GAE SDK安装到virtualenv中,具体描述可以参考这里

1

我认为,由于您已经使用了 --no-site-packages 选项设置了 virtualenv,您需要将 SDK 安装到该环境中。--no-site-packages 将您正在配置的开发环境与计算机上的任何其他 Python 安装隔离开来,因此,正如您似乎已经配置的那样,您正在调用一个不存在的模块(在该环境中),这就是为什么在停用环境时它可以工作(此时运行默认 OS 安装的 Python)。如果要能够访问环境外的模块,请尝试在不使用 --no-site-packages 选项的情况下设置开发环境。


在使用virtualenv时,通常会使用--no-site-packages选项以避免污染。 - Lionel

1

我有点晚加入这个对话,但我刚遇到同样的问题,然后偶然发现了gae_installer,你可以用pip install gae_installer的方式安装它。这将直接将Google应用引擎(GAE)SDK放置在您的Python路径中。希望其他人会发现这很有用。


你是在虚拟环境内还是外部执行的这个操作? - vlsd

0

和bozzo的答案一样。以下是说明:

这在GAE的Issue 4339中有描述。以下是修复方法:

  1. 在此处下载补丁:patch
  2. 将补丁移动到google_appengine/google/appengine/tools/
  3. 将工作目录更改为与上述路径相同的路径
  4. 键入:patch -p0 < dev_appserver.patch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接