Как получить доступ к ${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)
Если кто-нибудь знает более приятное решение, добро пожаловать:)