Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to get Registry().settings during Pyramid app startup time?
    text
    copied!<p>I am used to develop web applications on Django and gunicorn.</p> <p>In case of Django, any application modules in a Django application can get deployment settings through <em>django.conf.settings</em>. The "settings.py" is written in Python, so that any arbitrary settings and pre-processing can be defined <strong>dynamically</strong>.</p> <p>In case of gunicorn, it has three configuration places in order of precedence, and one settings registry class instance combines those.(But usually these settings are used only for gunicorn not application.)</p> <ol> <li>Command line parameters.</li> <li>Configuration file. (like Django, written in Python which can have any arbitrary settings <strong>dynamically</strong>.)</li> <li>Paster application settings.</li> </ol> <p>In case of Pyramid, according to Pyramid documentation, deployment settings may be usually put into <em>pyramid.registry.Registry().settings</em>. But it seems to be accessed only when a <em>pyramid.router.Router()</em> instances exists. That is pyramid.threadlocal.get_current_registry().settings returns None, during the startup process in an application "main.py".</p> <p>For example, I usually define some business logic in SQLAlchemy model modules, which requires deployment settings as follows.</p> <p><code>myapp/models.py</code></p> <pre><code>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) </code></pre> <p>But, "settings['external_api_endpoint']" raises a TypeError exception because the "settings" is None.</p> <p>I thought two solutions.</p> <ul> <li><p>Define a callable which accepts "config" argument in "models.py" and "main.py" calls it with a Configurator() instance.</p> <p><code>myapp/models.py</code></p> <pre><code>from sqlalchemy import Table, Column, Types from sqlalchemy.orm import mapper from myapp.db import session, metadata _g = globals() def initialize(config): settings = config.get_settings() mytable = Table('mytable', metadata, Column('id', Types.INTEGER, rimary_key = True,) (other columns ...) ) class MyModel(object): query = session.query_property() external_api_endpoint = settings['external_api_endpoint'] def get_api_result(self): (interact with external api)... mapper(MyModel, mytable) _g['MyModel'] = MyModel _g['mytable'] = mytable </code></pre></li> <li><p>Or, put an empty module "app/settings.py", and put setting into it later.</p> <p><code>myapp/__init__.py</code></p> <pre><code>from pyramid.config import Configurator from .resources import RootResource def main(global_config, **settings): config = Configurator( settings = settings, root_factory = RootResource, ) import myapp.settings myapp.setting.settings = config.get_settings() (other configurations ...) return config.make_wsgi_app() </code></pre></li> </ul> <p>Both and other solutions meet the requirements, but I feel troublesome. What I want is the followings.</p> <ul> <li><p>development.ini</p> <p>defines rough settings because development.ini can have only <strong>string</strong> type constants.</p> <pre><code>[app:myapp] use = egg:myapp env = dev0 api_signature = xxxxxx </code></pre></li> <li><p>myapp/settings.py</p> <p>defines detail settings based on development.ini, beacause any arbitrary variables(types) can be set.</p> <pre><code>import datetime, urllib from pytz import timezone from pyramid.threadlocal import get_current_registry pyramid_settings = get_current_registry().settings if pyramid_settings['env'] == 'production': api_endpoint_uri = 'http://api.external.com/?{0}' timezone = timezone('US/Eastern') elif pyramid_settings['env'] == 'dev0': api_endpoint_uri = 'http://sandbox0.external.com/?{0}' timezone = timezone('Australia/Sydney') elif pyramid_settings['env'] == 'dev1': api_endpoint_uri = 'http://sandbox1.external.com/?{0}' timezone = timezone('JP/Tokyo') api_endpoint_uri = api_endpoint_uri.format(urllib.urlencode({'signature':pyramid_settings['api_signature']})) </code></pre></li> </ul> <p>Then, other modules can get arbitrary deployment settings through "import myapp.settings". Or, if Registry().settings is preferable than "settings.py", **settings kwargs and "settings.py" may be combined and registered into Registry().settings during "main.py" startup process.</p> <p>Anyway, how to get the settings dictionay during startup time ? Or, Pyramid gently forces us to put every code which requires deployment settings in "views" callables which can get settings dictionary anytime through <em>request.registry.settings</em> ?</p> <hr> <p><strong>EDIT</strong></p> <p>Thanks, Michael and Chris.</p> <p>I at last understand why Pyramid uses threadlocal variables(registry and request), in particular registry object for more than one Pyramid applications.</p> <p>In my opinion, however, deployment settings usually affect business logics that may define application-specific somethings. Those logics are usually put in one or more Python modules that may be other than "app/<strong>init</strong>.py" or "app/views.py" that can easily get access to Config() or Registry(). Those Python modules are normally "global" at Python process level.</p> <p>That is, even when more than one Pyramid applications coexist, despite their own threadlocal variables, they have to share those "global" Python modules that may contain applicatin-specific somethings at Python process level.</p> <p>Of cause, every those modules can have "initialize()" callalbe which is called with a Configurator() by the application "main" callable, or passing Registory() or Request() object through so long series of function calls can meet usual requirements. But, I guess Pyramid beginers (like me) or developers who has "large application or so many settings" may feel troublesome, although that is Pyramid design.</p> <p>So, I think, Registry().settings should have only real "thread-local" variables, and should not have normal business-logic settings. Responsibility for segregation of multiple application-specific module, classes, callables variables etc. should be taken by developer. As of now, from my viewpoint, I will take Chris's answer. Or in "main" callable, do "execfile('settings.py', settings, settings)" and put it in some "global" space.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload