如何使用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在这里安装软件包>
- 站点包
- 的python2.5
- 包括
- 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上
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文件夹中。