Как мне управлять сторонними библиотеками Python с помощью Google App Engine?(virtualenv? pip?) - PullRequest
61 голосов
/ 01 февраля 2011

Какова лучшая стратегия для управления сторонними библиотеками Python с помощью Google App Engine?

Скажем, я хочу использовать 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 может импортировать модули из zip-файлов и что pip может работать с замечательным файлом REQUIREMENTS, и я видел, что pip имеет команду zip для использования с GAE.

(Примечание: есть несколько похожих вопросов - 1 , 2 , 3 , 4 , 5 - но они зависят от конкретного случая и на самом деле не отвечают на мой вопрос.)

Ответы [ 6 ]

70 голосов
/ 01 февраля 2011

Вот как я это делаю:

  • проект
    • .Python
    • bin
    • lib
      • python2.5
        • site-packages
          • <пакеты для установки pip здесь>
    • include
    • src
      • app.yaml
      • index.yaml
      • main.yaml
      • <символьная ссылка на пакеты, установленные в pip в ../lib/python2.5 / site-packages </li>

Каталог project - это каталог верхнего уровня, в котором находится virtualenv.Я получаю virtualenv с помощью следующих команд:

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

В каталоге src находится весь ваш код.Когда вы развертываете свой код в GAE, * only * развертывает те, что находятся в каталоге 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 с.В моем случае я использую Toscawidgets2, и мне пришлось копаться в исходном коде, чтобы вручную соединить кусочки.Это может раздражать, если у вас много библиотек, которые используют entry_point.

45 голосов
/ 29 августа 2014

Как насчет просто:

$ 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 метод развертывания.

6 голосов
/ 03 апреля 2013

Я предпочитаю 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.

Вы также можете использовать его для вставки переменных в шаблоны конфигурационных файлов, например, для установки идентификатора и версии appspot в app.yaml, если у вас есть промежуточный сервер с staging.cfg и т. Д.

4 голосов
/ 26 июня 2013

Я недавно создал инструмент для этого под названием gaenv.Он соответствует формату require.txt, но не устанавливает его, вы можете установить его с помощью pip install -r needs.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

2 голосов
/ 14 сентября 2014

Решение Wernight является наиболее близким к текущей практике в официальном официальном примере приложения Flask , которое я уже улучшил, изменив вызов 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/ работать для всех пакетов, включая пакеты пространства имен, и все еще разрешать переопределение включенных библиотек новыми версиями, поскольку я до сих пор не мог чтобы найти более простую альтернативу .

2 голосов
/ 18 марта 2011

Примечание. Этот ответ относится только к Flask в Google App Engine.

См. Проект 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

Пакеты, отличные от Flask, можно помещать в папку src / packages в виде zip-файлов, яиц или разархивированных пакетов, поскольку шаблон проекта включает в себя фрагмент кода sys.path.insert (), размещенный выше.

...