Как мне управлять сторонними библиотеками Python с помощью Google App Engine? (virtualenv? pip?)
Какая лучшая стратегия для управления сторонними библиотеками Python с Google App Engine?
Скажем, я хочу использовать флешку, структуру 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 ...)
Должен быть лучший способ управлять сторонним кодом, особенно если я хочу отслеживать версии, тестировать обновления или если две библиотеки совместно используют подкаталог. Я знаю, что Python может импортировать модули из zip файлов, и этот пип может работать с замечательным файлом ТРЕБОВАНИЙ, и я видел, что у пипа есть команда zip
для использования с GAE.
(Примечание: Есть несколько подобных вопросов - 1, 2, 3, 4, 5 - но они зависят от конкретного случая и на самом деле не отвечаю на мой вопрос.)
Ответы
Ответ 1
Как насчет просто:
$ 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'))
UPDATE:
Google обновил свой образец до appengine_config.py
, например:
from google.appengine.ext import vendor
vendor.add('lib')
Примечание. Несмотря на то, что в их примере .gitignore
игнорируется каталог lib/
, вам все равно нужно сохранить этот каталог под контролем источника, если вы используете метод git-push
deploy.
Ответ 2
Вот как я это делаю:
- Проект
- .Python
- бен
- Lib
- включить
- ЦСИ
- app.yaml
- index.yaml
- main.yaml
- < symlink установил пакеты в.. /lib/python 2.5/site-packages
Каталог 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)
После этого вы можете импортировать свои почтовые пакеты как обычно.
Одна вещь, на которую нужно обратить внимание, - setuptools 'pkg_resources.py
. Я скопировал это непосредственно в мой каталог src
, чтобы мои другие символические пакеты могли его использовать. Следите за тем, что использует entry_point
s. В моем случае я использую Toscawidgets2, и мне пришлось копаться в исходном коде, чтобы вручную подключить фрагменты. Это может раздражать, если у вас много библиотек, которые полагаются на entry_point
.
Ответ 3
Я предпочитаю buildout.
Вы устанавливаете зависимости в файле setup.py в своем проекте или buildout.cfg, привязываете версии в файле buildout.cfg и указываете, какие пакеты недоступны в GAE и должны быть включены в packages.zip. rod.recipe.appengine скопирует необходимые пакеты в packages.zip и до тех пор, пока вы вставляете package.zip в sys.path, их можно импортировать где угодно.
Вы также можете использовать вилки из github, если пакет вам не нужен на pypi
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.
Вы также можете использовать его для вставки переменных в шаблоны конфигурационных файлов, например, для установки id и версии appspot в app.yaml, если у вас есть промежуточный сервер с staging.cfg и т.д.
Ответ 4
Недавно я создал инструмент для этого, называемый gaenv. Он следует в формате requirements.txt, но не устанавливает его, вы можете установить с помощью pp install -r requirements.txt, затем запустить инструмент командной строки gaenv.
$ pip install -r requirements.txt
$ gaenv
Это создает символические ссылки автоматически, вы также можете установить gaenv в свой virtualenv и запустить двоичный файл.
Вот сообщение в блоге об этом:
http://blog.altlimit.com/2013/06/google-app-engine-virtualenv-tool-that.html
также на github
https://github.com/faisalraja/gaenv
Ответ 5
Примечание: этот ответ специфичен для Flask в Google App Engine.
См. проект шаблона-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
Пакеты Non-Flask можно отбросить в папку src/packages в виде файлов zip, яиц или распакованных пакетов, поскольку шаблон проекта включает в себя фрагмент sys.path.insert(), опубликованный выше.
Ответ 6
Решение Wernight находится ближе всего к текущей практике в официальном примере флэша, который я уже улучшил, изменив вызов sys.path.insert()
на site.addsitedir()
, чтобы разрешить пакеты имен путем обработки их сопутствующих .pth
(что важно для таких фреймворков, как Pyramid).
Пока что так хорошо, но добавляет каталог в путь и поэтому теряет возможность переопределять включенные библиотеки (например, 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)
или какой-либо другой вариант, как вы можете видеть в обсуждении этого запроса на перенос, но логика более или менее основана на том, как она будет работать независимо, чтобы позволить простой pip install -r requirements.txt -t lib/
работать для всех пакетов, включая пространства имен, и по-прежнему допускать переопределение включенных библиотек с новыми версиями, поскольку я до сих пор был неспособным найти более простую альтернативу.