如何使用Google App Enginepipe理第三方Python库? (virtualenv?pip?)

使用Google App Enginepipe理第三方Python库的最佳策略是什么?

假设我想使用Flask,一个webapp框架。 博客文章说这样做,这似乎不正确:

$ cd /tmp/ $ wget http://pypi.python.org/packages/source/F/Flask/Flask-0.6.1.tar.gz $ tar zxf Flask-0.6.1.tar.gz $ cp -r Flask-0.6.1/flask ~/path/to/project/ (... repeat for other packages ...) 

必须有一个更好的方法来pipe理第三方代码,特别是如果我想跟踪版本,testing升级,或者如果两个库共享一个子目录。 我知道Python可以从zip文件中导入模块,而且pip可以使用一个很好的需求文件,我已经看到pip有一个用于GAE的zip命令。

(注意:有一些类似的问题 – 1,2,3,4,5 – 但它们是特定的,并不真正回答我的问题。)

简单地说:

 $ pip install -r requirements.txt -t <your_app_directory/lib> 

创build/编辑<your_app_directory>/appengine_config.py

 """This file is loaded when starting a new application instance.""" import sys import os.path # add `lib` subdirectory to `sys.path`, so our `main` module can load # third-party libraries. sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'lib')) 

更新:

Google将其示例更新为appengine_config.py ,如下所示:

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

注意:即使他们的例子有.gitignore忽略lib/目录,如果使用git-push部署方法,仍然需要将该目录保存在源代码pipe理下。

以下是我如何做到这一点:

  • 项目
    • 。python
    • 箱子
    • LIB
      • 的python2.5
        • 站点包
          • <pip在这里安装软件包>
    • 包括
    • SRC
      • 的app.yaml
      • index.yaml中
      • main.yaml
      • <symlink安装的软件包中的../lib/python2.5/site-packages

project目录是virtualenv所在的顶级目录。 我使用以下命令获取virtualenv:

 cd project virtualenv -p /usr/bin/python2.5 --no-site-packages --distribute . 

src目录是你所有的代码去的地方。 当您将代码部署到GAE时, * *部署那些在src目录中的文件,而不是其他文件。 appcfg.py将parsing符号链接并将库文件复制到GAE。

我不会将我的库作为zip文件安装,主要是为了方便起见,以防我需要阅读源代码,我只是出于好奇而做了很多事情。 但是,如果您确实想压缩库,请将以下代码片段放入main.py中

 import sys for p in ['librarie.zip', 'package.egg'...]: sys.path.insert(0, p) 

之后,您可以照常导入压缩包。

有一点要注意的是setuptools的pkg_resources.py 。 我直接复制到我的src目录,所以我的其他符号链接的软件包可以使用它。 注意任何使用entry_point的东西。 在我的情况下,我正在使用Toscawidgets2,我不得不深入源代码手动连接件。 如果你有很多依靠entry_point的库, entry_point

我更喜欢buildout 。

您可以在您的项目或buildout.cfg中的setup.py中设置依赖关系,将这些版本固定在buildout.cfg中,并指定哪些程序包在GAE上不可用,并且应该包含在packages.zip中。 rod.recipe.appengine会将所需的软件包复制到packages.zip中,只要将packages.zip插入到sys.path中,就可以将其导入到任何地方。

如果你需要的软件包不在pypi上,你也可以使用github上的fork

 find-links = https://github.com/tesdal/pusher_client_python/tarball/rewrite#egg=pusher-2.0dev2 [versions] pusher = 2.0dev2 

所有这些设置和依赖都在git中进行了版本化。

不要想知道你的源代码树中现在包含了哪一个Flask的副本,并且可能复制到你的版本控制中(或者需要新的开发者手动解包和升级),你只需在buildout.cfg中检查版本即可。 如果你想要一个新版本,改变buildout.cfg并重新运行buildout。

您也可以使用它将variables插入到configuration文件模板中,如在app.yaml中设置appspot id和版本(如果使用staging.cfg等login服务器)。

我最近创build了一个名为gaenv的工具。 它遵循requirements.txt格式,但不安装,可以使用pip install -r requirements.txt进行安装,然后运行命令行工具gaenv。

 $ pip install -r requirements.txt $ gaenv 

这会自动创build符号链接,你可以在你的virtualenv中安装gaenv并从那里运行二进制文件。 这是一篇关于它的博客文章:

http://blog.altlimit.com/2013/06/google-app-engine-virtualenv-tool-that.html

也在github上

https://github.com/faisalraja/gaenv

Wernight的解决scheme与官方Flask示例应用程序中的最近实践最为接近,我已经通过将sys.path.insert()调用更改为site.addsitedir() ,以便通过处理其服务人员来允许命名空间包来改进.pth文件(这对Pyramid等框架很重要)。

目前为止还不错,但目录追加到path中,因此失去了使用较新版本覆盖包含的库(如WebOb和请求)的机会。

然后在appengine_config.py需要什么(以及我正试图将这个改变也接受到官方回购中)如下:

 """This file is loaded when starting a new application instance.""" import os.path import site.addsitedir import sys.path dirname = 'lib' dirpath = os.path.join(os.path.dirname(__file__), dirname) # split path after 1st element ('.') so local modules are always found first sys.path, remainder = sys.path[:1], sys.path[1:] # add `lib` subdirectory as a site directory, so our `main` module can load # third-party libraries. site.addsitedir(dirpath) # append the rest of the path sys.path.extend(remainder) 

这个代码的最终版本最终可能会隐藏在vendor.py模块中,并且像调用insertsitedir(index, path)或者其他一些变体一样被调用,就像你在参与这个pull请求的讨论中看到的一样 ,但是逻辑或多或less它将如何工作, pip install -r requirements.txt -t lib/ ,允许一个简单的pip install -r requirements.txt -t lib/为所有包括命名空间的包工作,并且仍然允许用新版本覆盖包含的库,因为我到目前为止一直无法find一个更简单的select 。

注意:这个答案是针对Google App Engine上的Flask的。

请参阅flask-appengine-template项目,以获取如何让Flask扩展在App Engine上工作的示例。 https://github.com/kamalgill/flask-appengine-template

把扩展名放到src / packages / flaskext的命名空间包文件夹中,你就完成了。 https://github.com/kamalgill/flask-appengine-template/tree/master/src/lib/flaskext

由于项目模板包含上面提到的sys.path.insert()片段,因此非Flask包可以作为zip文件,蛋或解压缩包放入src / packages文件夹中。