Я использую для разработки веб-приложений на Django и gunicorn.
В случае Django любые модули приложения в приложении Django могут получить настройки развертывания через django.conf.settings ]. "Settings.py" написан на Python, так что любые произвольные настройки и предварительная обработка могут быть определены динамически .
В случае Gunicorn он имеет три места конфигурации в порядке приоритета , и один экземпляр класса реестра настроек объединяет их. (Но обычно эти настройки используются только для gunicorn, а не приложения.)
В случае Pyramid, согласно документации Pyramid, настройки развертывания обычно могут быть помещены в pyramid.registry.Registry (). settings . Но похоже, что доступ к нему возможен только тогда, когда существует экземпляр pyramid.router.Router () . Это pyramid.threadlocal.get_current_registry (). Settings возвращает None во время процесса запуска в приложении main.py.
Например, я обычно определяю некоторую бизнес-логику в модулях модели SQLAlchemy, для чего требуются следующие параметры развертывания .
myapp / models.py
from sqlalchemy import Table, Column, Types
from sqlalchemy.orm import mapper
from pyramid.threadlocal import get_current_registry
from myapp.db import session, metadata
settings = get_current_registry().settings
mytable = Table('mytable', metadata,
Column('id', Types.INTEGER, primary_key=True,)
(other columns)...
)
class MyModel(object):
query = session.query_property()
external_api_endpoint = settings['external_api_uri']
timezone = settings['timezone']
def get_api_result(self):
(interact with external api ...)
mapper(MyModel, mytable)
Но «settings ['external_api_endpoint']» вызывает исключение TypeError, потому что «settings» - None.
Я подумал о двух решениях.
Определите вызываемый объект, который принимает Аргумент config в models.py и main.py вызывает его с Экземпляр Configurator ().
myapp / models.py
из sqlalchemy import Table, Column, Types
из sqlalchemy.orm import mapper
из сеанса импорта myapp.db, метаданные
_g = globals ()
def инициализация (конфигурация):
настройки = config.get_settings ()
mytable = Таблица ('mytable', метаданные,
Столбец ('id', Types.INTEGER, rimary_key = True,)
(другие столбцы ...)
)
класс MyModel (объект):
query = session.query_property ()
external_api_endpoint = настройки ['external_api_endpoint']
def get_api_result (сам):
(взаимодействовать с внешним API) ...
картограф (MyModel, mytable)
_g ['MyModel'] = MyModel
_g ['mytable'] = mytable
Или поместите пустой модуль «app / settings.py» и внесите в него настройки позже.
myapp / __ init __. Py
из конфигуратора импорта pyramid.config
из .resources import RootResource
def main (global_config, ** настройки):
config = Конфигуратор (
settings = настройки,
root_factory = RootResource,
)
импортировать myapp.settings
myapp.setting.settings = config.get_settings ()
(другие конфигурации ...)
вернуть config.make_wsgi_app ()
Оба и другие решения соответствуют требованиям, но я чувствую неудобства. Я хочу следующее.
development.ini
определяет приблизительные настройки, потому что development.ini может иметь только константы типа string .
[приложение: myapp]
использовать = яйцо: myapp
env = dev0
api_signature = xxxxxx
myapp / settings.py
определяет подробные настройки на основе development.ini, поскольку могут быть установлены любые произвольные переменные (типы).
import datetime, urllib
из часового пояса импорта pytz
из pyramid.threadlocal import get_current_registry
pyramid_settings = get_current_registry (). настройки
если pyramid_settings ['env'] == 'production':
api_endpoint_uri = 'http://api.external.com/?{0}'
timezone = часовой пояс ('США / Восток')
elif pyramid_settings ['env'] == 'dev0':
api_endpoint_uri = 'http://sandbox0.external.com/?{0}'
timezone = timezone ('Австралия / Сидней')
elif pyramid_settings ['env'] == 'dev1':
api_endpoint_uri = 'http://sandbox1.external.com/?{0}'
timezone = часовой пояс ('JP / Tokyo')
api_endpoint_uri = api_endpoint_uri.format (urllib.urlencode ({'подпись': pyramid_settings ['api_signature']}))
Затем другие модули могут получить произвольные настройки развертывания с помощью «import myapp.settings». Или, если Registry (). Settings предпочтительнее, чем "settings.py", ** параметры kwargs и "settings.py" могут быть объединены и зарегистрированы в Registry (). Settings во время процесса запуска "main.py".
В любом случае, как получить словарь настроек во время запуска? Или Pyramid мягко заставляет нас помещать каждый код, требующий настроек развертывания, в вызываемые файлы "views", которые могут получить словарь настроек в любое время через request.registry.settings ?
EDIT
Спасибо, Майкл и Крис .
Я наконец понимаю, почему Pyramid использует локальные переменные потока (реестр и запрос), в частности объект реестра для более чем одного приложения Pyramid.
Однако, на мой взгляд, настройки развертывания обычно влияют на бизнес-логику, которая может определять приложения. конкретные вещи. Эта логика обычно помещается в один или несколько модулей Python, которые могут отличаться от «app / init .py» или «app / views.py», которые могут легко получить доступ к Config () или Реестр (). Эти модули Python обычно являются «глобальными» на уровне процесса Python.
То есть, даже когда сосуществуют несколько приложений Pyramid, несмотря на их собственные локальные переменные потока, они должны совместно использовать те «глобальные» модули Python, которые могут содержать специфичные для приложения что-то на уровне процесса Python.
Конечно, каждый из этих модулей может иметь callalbe "initialize ()", который вызывается с помощью Configurator () вызываемым "основным" приложением или передает объект Registory () или Request () через поэтому длинные серии вызовов функций могут удовлетворить обычные требования. Но, я полагаю, новички в Pyramid (такие как я) или разработчики, у которых есть «большое приложение или так много настроек», могут почувствовать проблемы, хотя это дизайн пирамиды.
Так что, я думаю, Registry (). Settings должны иметь только реальные " "локальные для потока" переменные и не должны иметь нормальных настроек бизнес-логики. Ответственность за разделение нескольких специфичных для приложения модулей, классов, вызываемых переменных и т. Д. Должен взять на себя разработчик. На данный момент, с моей точки зрения, я приму ответ Криса. Или в «основном» вызываемом файле выполните команду «execfile ('settings.py', settings, settings)» и поместите его в какое-то «глобальное» пространство.