Как мне управлять сторонними библиотеками 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
      • python2.5
        • сайт-пакеты
          • < pip здесь >
    • включить
    • ЦСИ
      • 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/ работать для всех пакетов, включая пространства имен, и по-прежнему допускать переопределение включенных библиотек с новыми версиями, поскольку я до сих пор был неспособным найти более простую альтернативу.