Как получить настройки Registry (). во время запуска приложения Pyramid?

Я использую для разработки веб-приложений на Django и gunicorn.

В случае Django любые модули приложения в приложении Django могут получить настройки развертывания через django.conf.settings ]. "Settings.py" написан на Python, так что любые произвольные настройки и предварительная обработка могут быть определены динамически .

В случае Gunicorn он имеет три места конфигурации в порядке приоритета , и один экземпляр класса реестра настроек объединяет их. (Но обычно эти настройки используются только для gunicorn, а не приложения.)

  1. Параметры командной строки.
  2. Файл конфигурации. (например, Django, написанный на Python, который может иметь любые произвольные настройки динамически .)
  3. Настройки приложения Paster.

В случае 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)» и поместите его в какое-то «глобальное» пространство.

21
задан takaomag 30 June 2011 в 07:39
поделиться