Python 在金字塔中的非请求上下文中检索应用程序配置设置

Python 在金字塔中的非请求上下文中检索应用程序配置设置,python,pyramid,Python,Pyramid,在我正在构建的金字塔应用程序(称为pyplay)中,我需要检索development.ini中的应用程序设置。问题是,我试图获取该设置的位置无法访问请求变量(例如,在模块文件的顶层) 所以,在阅读了文档中的这个示例之后:我开始做一些非常简单和硬编码的事情,开始只是为了让它工作。 由于my development.ini有以下部分:[app:main],因此我尝试的简单示例如下: from paste.deploy.loadwsgi import appconfig config = appcon

在我正在构建的金字塔应用程序(称为pyplay)中,我需要检索development.ini中的应用程序设置。问题是,我试图获取该设置的位置无法访问请求变量(例如,在模块文件的顶层)

所以,在阅读了文档中的这个示例之后:我开始做一些非常简单和硬编码的事情,开始只是为了让它工作。 由于my development.ini有以下部分:[app:main],因此我尝试的简单示例如下:

from paste.deploy.loadwsgi import appconfig
config = appconfig('config:development.ini', 'main', relative_to='.')
但应用程序拒绝启动并显示以下错误:

ImportError: <module 'pyplay' from '/home/pish/projects/pyplay/__init__.pyc'> has no 'main' attribute
在这一点上,我有点卡住了,我不知道我做错了什么。谁能帮我一把吗

提前谢谢

编辑:以下是我的development.ini文件的内容(请注意,pish.theparam是我试图获取的设置):


在金字塔中很难做到这一点的原因是,使用模块级设置总是一个坏主意。这意味着每个进程只能以一种方式使用模块(不同的代码路径不能以不同的方式使用库)。:-)

无法访问请求对象的一种方法是,至少在函数调用后隐藏全局函数,这样全局函数在每个线程中都是不同的(基本上是每个请求)


步骤1:在文件xyz_文件中创建一个单例类

步骤2:在“_uuu_uuuu.py”中

步骤3:您应该能够访问代码的任何部分

  from xyz_file import ApplicationSettings
  app_settings = ApplicationSettings().get_application_configuration()

基本上,如果您没有访问请求对象的权限,那么您在金字塔中“偏离轨道”。为了以金字塔的方式做事情,我们制作组件并找出它们在金字塔生命周期中的位置,它们应该始终可以直接访问注册表(ZCA)和请求中的一个或两个

如果您所做的不符合请求生命周期的要求,那么它可能是应该在服务器启动时实例化的内容,通常是在您的init.py中构建并填充配置程序(我们对注册表的访问)。不要害怕使用注册表来允许其他组件在以后“伪全局”地进行操作。因此,您可能希望为您的东西创建某种工厂,在启动代码中调用工厂,可能将对注册表的引用作为参数传递,然后将对象附加到注册表。如果您的组件需要与请求生命周期代码接口,请为其提供一个将请求作为参数的方法。稍后,这个对象需要的任何东西都可以从注册表中获取,这个对象需要获取的任何东西都可以通过注册表或请求来完成

您完全可以使用另一个答案中的hack来访问当前的全局注册表,但需要这样做的是一种代码气味,您可以找到更好的设计来消除这种气味

伪代码示例,在服务器启动代码中:

# in in the init block where our Configurator has been built
from myfactory import MyFactory
registry.my_component = MyFactory(config.registry)
# you can now get at my_component from anywhere in a pyramid system
您的组件:

class MyFactory(oject):
    def __init__(self, registry):
        # server start up lifecycle stuff here    
        self.registry = registry

    def get_something(self, request):
        # do stuff with the rest of the system
        setting_wanted = self.registry.settings['my_setting']

金字塔视图就是这样工作的。它们实际上是请求和上下文的多适配器。它们的工厂在注册表中注册,然后当视图查找过程开始时,工厂实例化一个作为参数传入请求的视图

你的development.ini文件是什么样子的?@Peter,我刚刚编辑了这个问题并添加了development.ini文件的内容。谢谢谢谢你的解释,迈克尔。我在想的一件事是,如果我试图获取的这个设置将用于设置某些sqlalchemy模型的
\uuu table\u args\uuuu
,那么从具有这些模型定义的.py的顶级范围调用这个函数可能不会为注册表返回任何内容。对吗?在处理这个问题时,我发现在“运行时”更改sqlalchemy模型的
\uu表\u参数\uuu
在查询调用中没有任何效果(就像它忽略了更改一样)。是的,不幸的是,sqlalchemy使模型配置变得困难。模块级设置还依赖于一些事情,比如在设置之后导入模块,以及类似的有趣的事情。对于类似SQLAlchemy的东西,我可能会采用
DBSession
方法,即在所有其他模块导入的某个
meta
模块中设置它,并且确保不要首先导入那些其他模块。
class Singleton:
def __init__(self, klass):
    self.klass = klass
    self.instance = None
def __call__(self, *args, **kwds):
    if self.instance == None:
        self.instance = self.klass(*args, **kwds)
    return self.instance

@Singleton
class ApplicationSettings(object):
   def __init__(self, app_settings=None):
       if app_settings is not None :
           self._settings = app_settings
   def get_appsettings_object(self):
       return self

   def get_application_configuration(self):
       return self._settings
def main(global_config, **settings):
  ....
  .......
  app_settings = ApplicationSettings(settings)
  from xyz_file import ApplicationSettings
  app_settings = ApplicationSettings().get_application_configuration()
# in in the init block where our Configurator has been built
from myfactory import MyFactory
registry.my_component = MyFactory(config.registry)
# you can now get at my_component from anywhere in a pyramid system
class MyFactory(oject):
    def __init__(self, registry):
        # server start up lifecycle stuff here    
        self.registry = registry

    def get_something(self, request):
        # do stuff with the rest of the system
        setting_wanted = self.registry.settings['my_setting']