Google App Engine으로 타사 Python 라이브러리를 관리하려면 어떻게하나요? (virtualenv? pip?)
Google App Engine으로 타사 Python 라이브러리를 관리하는 가장 좋은 전략은 무엇인가요?
웹앱 프레임 워크 인 Flask를 사용하고 싶다고 가정 해 보겠습니다. 블로그 항목에 이렇게하려면 옳지 않은 것 같습니다.
$ 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 ...)
특히 버전, 테스트 업그레이드를 추적하거나 두 라이브러리가 하위 디렉터리를 공유하는 경우 타사 코드를 관리하는 더 나은 방법이 있어야합니다. Python이 zipfile에서 모듈을 가져올 수 있고 pip 가 멋진 REQUIREMENTS 파일과 함께 작동 할 수 있다는 것을 알고 있으며 pipzip
에 GAE와 함께 사용할 명령이 있음을 확인했습니다.
(참고 : 1 , 2 , 3 , 4 , 5 와 같은 몇 가지 유사한 질문 이 있지만 사례별로 다르며 실제로 제 질문에 답변하지 않습니다.)
간단히 :
$ pip install -r requirements.txt -t <your_app_directory/lib>
생성 / 편집 <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
배포 방법 을 사용하는 경우 해당 디렉터리를 소스 제어하에 유지해야합니다 .
방법은 다음과 같습니다.
- 계획
- .Python
- 큰 상자
- lib
- 파이썬 2.5
- 사이트 패키지
- <여기에 pip 설치 패키지>
- 사이트 패키지
- 파이썬 2.5
- 포함
- src
- app.yaml
- index.yaml
- main.yaml
- <../lib/python2.5/site-packages에있는 pip 설치 패키지를 심볼릭 링크합니다.
project
디렉토리는 VIRTUALENV가 앉아 최상위 디렉토리입니다. 다음 명령을 사용하여 virtualenv를 얻습니다.
cd project
virtualenv -p /usr/bin/python2.5 --no-site-packages --distribute .
src
모든 코드는 어디로 디렉토리입니다. 코드를 GAE에 배포 할 때 * 만 * src 디렉토리에 배포하고 다른 것은 배포하지 마십시오 . 는 appcfg.py
심볼릭 링크를 해결하고 당신을 위해 GAE에 라이브러리 파일을 복사합니다.
소스 코드를 읽어야하는 경우를 대비하여 주로 편의를 위해 라이브러리를 zip 파일로 설치하지 않습니다. 그러나 실제로 라이브러리를 압축하려면 다음 코드를 main.py에 넣으십시오.
import sys
for p in ['librarie.zip', 'package.egg'...]:
sys.path.insert(0, p)
그런 다음 평소처럼 압축 된 패키지를 가져올 수 있습니다.
One thing to watch out for is setuptools' pkg_resources.py
. I copied that directly into my src
directory so my other symlinked packages can use it. Watch out for anything that uses entry_point
s. In my case I'm using Toscawidgets2 and I had to dig into the source code to manually wire up the pieces. It can become annoying if you had a lot of libraries that rely on entry_point
.
I prefer buildout.
You set up dependencies in setup.py in your project or buildout.cfg, pin the versions in buildout.cfg, and specify which packages are not available on GAE and should be included in packages.zip. rod.recipe.appengine will copy required packages into packages.zip, and as long as you insert packages.zip into the sys.path, they can be imported anywhere.
You can also use forks from github if the package you need is not on pypi
find-links =
https://github.com/tesdal/pusher_client_python/tarball/rewrite#egg=pusher-2.0dev2
[versions]
pusher = 2.0dev2
and all of these settings and dependencies are versioned in git.
Instead of wondering which copy of Flask is currently included in your source tree and perhaps copied into your version control (or requiring new developers to manually unpack and upgrade), you simply check the version in buildout.cfg. If you want a new version, change buildout.cfg and rerun buildout.
You can also use it to insert variables into config file templates, like setting the appspot id and version in app.yaml if you have staging server with staging.cfg and so on.
I recently created a tool for this called gaenv. It follows a requirements.txt format, but doesn't install it, you can install with pip install -r requirements.txt then run the command line tool gaenv.
$ pip install -r requirements.txt
$ gaenv
This creates symlinks automatically, you could install gaenv in your virtualenv too and run the binary from there. Here is a blog post about it:
http://blog.altlimit.com/2013/06/google-app-engine-virtualenv-tool-that.html
also on github
https://github.com/faisalraja/gaenv
Wernight's solution is the closest to current practice in the official Flask example app, which I've already improved by changing the sys.path.insert()
call to site.addsitedir()
in order to allow for namespace packages by processing their attendant .pth
files (which are important for frameworks like Pyramid).
So far so good, but that appends the directory to the path, and so loses the opportunity to override the included libraries (like WebOb and requests) with newer versions.
What is needed then in appengine_config.py
(and I am trying to get this change accepted into the official repos as well) is the following:
"""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)
The final version of this code may end up hidden away in a vendor.py
module and called like insertsitedir(index, path)
or some other variation, as you can see in the discussion attending this pull request, but the logic is more or less how it will work regardless, to allow a simple pip install -r requirements.txt -t lib/
to work for all packages including namespace ones, and to still allow overriding the included libraries with new versions, as I have so far been unable to find a simpler alternative.
Note: this answer is specific for Flask on Google App Engine.
See the flask-appengine-template project for an example of how to get Flask extensions to work on App Engine. https://github.com/kamalgill/flask-appengine-template
Drop the extension into the namespace package folder at src/packages/flaskext and you're all set. https://github.com/kamalgill/flask-appengine-template/tree/master/src/lib/flaskext
Non-Flask packages can be dropped into the src/packages folder as zip files, eggs, or unzipped packages, as the project template includes the sys.path.insert() snippet posted above.
'Program Tip' 카테고리의 다른 글
PHP에서 객체 연산자“->”를 어디에 사용합니까? (0) | 2020.11.30 |
---|---|
Android는 내 인 텐트 Extras를 계속 캐싱합니다. 새로운 추가 항목을 유지하는 보류중인 인 텐트를 선언하는 방법은 무엇입니까? (0) | 2020.11.30 |
Clojure에서 Java 클래스의 메소드를 얻으려면 어떻게해야합니까? (0) | 2020.11.30 |
Rails 3 및 Heroku : 푸시시 자동으로 "rake db : migrate"? (0) | 2020.11.30 |
Unix 찾기 : 여러 파일 유형 (0) | 2020.11.30 |