Как получить доступ к ${buildout:directory} из кода Python?

У меня есть веб-приложение Pyramid, управляемое с помощью zc.buildout. В нем мне нужно прочитать файл на диске, который находится в подкаталоге директории buildout.

Проблема заключается в определении пути к файлу - я не хочу жестко задавать абсолютный путь, и просто предоставление относительного пути не работает при обслуживании приложения в рабочей среде (предположительно, потому что рабочий каталог отличается).

Итак, многообещающие "крючки", о которых я думаю:

  • "корневой" каталог сборки, к которому я могу обратиться в buildout.cfg как ${buildout:directory} - однако, я не могу понять, как я могу "экспортировать" его, чтобы он мог быть доступен через код Python

  • расположение файла.ini Paster, который запускает приложение

3 ответа

Решение

Если путь к файлу относительно корня компоновки или местоположения файла paster.ini всегда один и тот же, что, как вам кажется, это из вашего вопроса, вы можете установить его в файле paster.ini:

[app:main]
...
config_file = %(here)s/path/to/file.txt

Затем получите доступ к нему из реестра, как в ответе Рейноута:

def your_view(request):
    config_file = request.registry.settings['config_file']

Как @MartijnPieters предлагает в комментарии к вашему собственному ответу, я бы использовал коллективно.recipe.template для создания записи в .ini, Я задавался вопросом, как я мог тогда получить доступ к этим данным в моем проекте, поэтому я решил это:-)

Давайте вернемся назад к тому, что вам нужно. Сначала в вашем коде представления, где вы хотите каталог для сборки:

def your_view(request):
    buildout_dir = request.registry.settings['buildout_dir']
    ....

request.registry.settings ( см. документацию) - это "объект настроек развертывания, похожий на диктонарную". Смотрите параметры развертывания, это **settings который передается в ваш основной метод, как def main(global_config, **settings)

Эти настройки находятся в [app:main] часть вашего deployment.ini или же production.ini файл. Так что добавьте каталог buildout там:

[app:main]
use = egg:your_app

buildout_dir = /home/you/wherever/it/is

pyramid.reload_templates = true
pyramid.debug_authorization = false
...

Но, и это последний шаг, вам не нужен этот жестко заданный путь. Так что сгенерируйте.ini с помощью шаблона. Шаблон development.ini.in использует ${partname:variable} язык расширения. в твоем случае тебе нужно${buildout:directory}:

[app:main]
use = egg:your_app

buildout_dir = ${buildout:dir}
#              ^^^^^^^^^^^^^^^

pyramid.reload_templates = true
pyramid.debug_authorization = false
...

Добавить часть сборки в buildout.cfg чтобы генерировать development.ini от development.ini.in:

[buildout]
...
parts =
    ...
    inifile
    ...

[inifile]
recipe = collective.recipe.template
input = ${buildout:directory}/development.ini.in
output = ${buildout:directory}/development.ini

Обратите внимание, что вы можете делать всякие классные вещи с коллективом Collect.recipe.template. ${serverconfig:portnumber} создать соответствующий номер порта в вашем production.ini и в вашем your_site_name.nginx.conf, например. Повеселись!

Вот довольно неуклюжее решение, которое я разработал:

В buildout.cfg я использовал extra-paths вариант zc.recipe.egg добавить каталог buildout в sys.path:

....
[webserver]
recipe = zc.recipe.egg:scripts
eggs = ${buildout:eggs}
extra-paths = ${buildout:directory}

тогда я положил файл с именем app_config.py в каталог сборки:

# This remembers the root of the installation (similar to {buildout:directory}
# so we can import it and use where we need access to the filesystem.
# Note: we could use os.getcwd() for that but it feels kinda wonky
# This is not directly related to Celery, we may want to move it somewhere
import os.path
INSTALLATION_ROOT = os.path.dirname(__file__)

Теперь мы можем импортировать его в наш код Python:

from app_config import INSTALLATION_ROOT
filename = os.path.join(INSTALLATION_ROOT, "somefile.ext")
do_stuff_with_file(filename)

Если кто-нибудь знает более приятное решение, добро пожаловать:)

Другие вопросы по тегам