Как мне управлять сторонними библиотеками 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 может импортировать модули из zipfiles, и этот пип может работать с замечательным файлом ТРЕБОВАНИЙ, и я видел, что у него есть команда zip для использования с GAE.

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

  • Википедия разрешает загрузку URL через Google App Engine?
  • Настройка Memcached для кэширования сеансов Django в App Engine
  • Управление аутентификацией пользователей в Google App Engine
  • Как сделать операции access_type = offline / server-only OAuth2 на GAE / Python?
  • Google App Engine / Drive SDK: ловить много исключений в отношении срока действия HTTP
  • Кэширование NDB при использовании прогнозируемых запросов
  • Как запустить приложение GAE на частном сервере?
  • Как заполнить переменные WTForm?
  • 6 Solutions collect form web for “Как мне управлять сторонними библиотеками Python с помощью Google App Engine? (virtualenv? pip?)”

    Что насчет просто:

     $ 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
        • python2.5
          • сайт-пакеты
            • <pip install packages here>
      • включают
      • ЦСИ
        • 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 разрешит символические appcfg.py и скопирует файлы библиотеки в GAE для вас.

    Я не устанавливаю свои библиотеки в качестве zip-файлов, в основном для удобства, если мне нужно прочитать исходный код, который, как мне кажется, очень много делается из любопытства. Однако, если вы действительно хотите заархивировать библиотеки, поместите следующий фрагмент кода в свой main.py

     import sys for p in ['librarie.zip', 'package.egg'...]: sys.path.insert(0, p) 

    После этого вы можете импортировать свои ZIP-пакеты, как обычно.

    Единственное, на что нужно обратить внимание, это pkg_resources.py ' pkg_resources.py . Я скопировал это прямо в мой каталог src чтобы мои другие символические пакеты могли его использовать. Следите за тем, что использует entry_point s. В моем случае я использую Toscawidgets2, и мне пришлось копаться в исходном коде, чтобы вручную подключить фрагменты. Это может раздражать, если у вас много библиотек, которые полагаются на entry_point .

    Я предпочитаю строить .

    Вы устанавливаете зависимости в файле setup.py в своем проекте или buildout.cfg, пишите версии в buildout.cfg и указываете, какие пакеты недоступны в GAE и должны быть включены в пакет .zip. rod.recipe.appengine скопирует необходимые пакеты в packages.zip и до тех пор, пока вы вставляете packages.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 и т. Д.

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

    Решение 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) или какой-либо другой вариант, как вы можете видеть в обсуждении этого запроса на pull , но логика более или менее как это будет работать независимо от того, чтобы позволить простой pip install -r requirements.txt -t lib/ работать для всех пакетов, включая пространства имен, и по-прежнему допускать переопределение включенных библиотек в новые версии, поскольку я до сих пор не смог найти более простую альтернативу .

    Примечание: этот ответ специфичен для 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 (), опубликованный выше.

    Python - лучший язык программирования в мире.