配置文件(初稿)

警告

这是一个新的API, 可以 告诉我们 你的想法

Bottle应用可以在 Bottle.config 这个类似于字典的对象中,存储它们的配置。这个对象在很多方面,影响着Bottle框架和相应的插件。你也可以在这个对象中,存储你的自定义配置。

基础知识

The Bottle.config object behaves a lot like an ordinary dictionary. All the common dict methods work as expected. Let us start with some examples:

import bottle
app = bottle.default_app()             # or bottle.Bottle() if you prefer

app.config['autojson']    = False      # Turns off the "autojson" feature
app.config['sqlite.db']   = ':memory:' # Tells the sqlite plugin which db to use
app.config['myapp.param'] = 'value'    # Example for a custom config value.

# Change many values at once
app.config.update({
    'autojson': False,
    'sqlite.db': ':memory:',
    'myapp.param': 'value'
})

# Add default values
app.config.setdefault('myapp.param2', 'some default')

# Receive values
param  = app.config['myapp.param']
param2 = app.config.get('myapp.param2', 'fallback value')

# An example route using configuration values
@app.route('/about', view='about.rst')
def about():
    email = app.config.get('my.email', 'nomail@example.com')
    return {'email': email}

app对象不一定总是可用的,但只要你在处理一个请求,你可以使用 request 对象来获得当前的应用对象和它的配置:

from bottle import request
def is_admin(user):
    return user == request.app.config['myapp.admin_user']

命名约定

方便起见,插件和应用应该遵循一些简单的规则,特别是在给配置参数命名的时候:

  • 所有的key都应该是小写的字符串,并符合Python的变量命名规则(除了下划线外,没有特殊字符)。
  • 命名空间通过点来区分(例如: namespace.fieldnamespace.subnamespacew.field )。
  • Bottle框架,使用根命名空间来存储它的配置。插件应该在它们自己的命名空间中存储它们的变量(例如: sqlite.db`werkzeug.use_debugger )。
  • 你的应用应该使用一个独立的命名空间(例如: myapp.* )。

从文件中加载配置

在你不想通过修改代码来修改配置的时候,配置文件是非常有用的。常见的配置文件语法如下:

[sqlite]
db = /tmp/test.db
commit = auto

[myapp]
admin_user = defnull

通过 ConfigDict.load_config() 方法,你可以从一些ini文件中导入配置:

app.config.load_config('/etc/myapp.conf')

从python模块加载配置

从Python模块加载配置是Python程序和框架的一种常见模式。 Bottle 假设配置键都是大写的:

您可以用 :met:`ConfigDict.load_module` ::

>>> c = ConfigDict()
>>> c.load_module('config')
{DEBUG: True, 'SQLITE.DB': 'memory'}
>>> c.load_module("config", False)
{'DEBUG': True, 'SQLITE': {'DB': 'memory'}}

注意第二个要禁用加载为命名空间项的参数,如中所示。 ConfigDict.load_dict() . 默认情况下,从python模块加载将调用此方法,除非使用 False 作为第二个论点。

从字典中加载配置

另外一个有用的方法,是 ConfigDict.load_dict() 。将字典中的配置,放到各自的命名空间下面:

# Load an entire dict structure
app.config.load_dict({
    'autojson': False,
    'sqlite': { 'db': ':memory:' },
    'myapp': {
        'param': 'value',
        'param2': 'value2'
    }
})

assert app.config['myapp.param'] == 'value'

# Load configuration from a json file
with open('/etc/myapp.json') as fp:
    app.config.load_dict(json.load(fp))

监听配置的变更

每次 Bottle.config 中的值有变更的时候,会触发 config 这个钩子。这个钩子可以用于在运行时,对配置的改动做出响应,例如连接到一个新的数据库,改变后台服务的debug配置,或更改线程池的大小。这个钩子接收两个参数(key, new_value),在 Bottle.config 中的值被改动之前触发。如果这个钩子抛出了异常,那么 Bottle.config 中的值将不会被改动。

@app.hook('config')
def on_config_change(key, value):
  if key == 'debug':
      switch_own_debug_mode_to(value)

这个钩子不能 改变 将要存到 Bottle.config 对象中的值。做这件事的是filter(过滤器)。

过滤器和其它元数据

ConfigDict 对象允许你给配置中每个key定义元数据。当前定义了help和filter:

帮助
一个描述字符串。可以被debug或管理工具利用,来帮助网站管理员填写配置。
滤波器
一个可运行的对象,接受和返回一个值。如果一个key定义了一个filter,任何将要存到这个key中的值,都会先传给filter的相应回调函数。在回调函数中,可做类型转换,有效性检验等工作。

这个功能比较适合被插件使用。它们可以检查它们的配置参数,或触发其它动作,或在 help 字段中,给配置添加说明:

class SomePlugin(object):
    def setup(app):
        app.config.meta_set('some.int', 'filter', int)
        app.config.meta_set('some.list', 'filter',
            lambda val: str(val).split(';'))
        app.config.meta_set('some.list', 'help',
            'A semicolon separated list.')

    def apply(self, callback, route):
        ...

import bottle
app = bottle.default_app()
app.install(SomePlugin())

app.config['some.list'] = 'a;b;c'     # Actually stores ['a', 'b', 'c']
app.config['some.int'] = 'not an int' # raises ValueError

API文档

class ConfigDict[源代码]

一个类似dict的配置存储,额外支持名称空间、验证器、元数据、覆盖等等。

这个类似dict的类为读访问进行了大量优化。所有只读方法以及项目访问都应该和内置dict一样快。

load_module(path, squash=True)[源代码]

从python模块加载值。

示例模式 config.py ::

DEBUG = True
SQLITE = {
    "db": ":memory:"
}
>>> c = ConfigDict()
>>> c.load_module('config')
{DEBUG: True, 'SQLITE.DB': 'memory'}
>>> c.load_module("config", False)
{'DEBUG': True, 'SQLITE': {'DB': 'memory'}}
参数:squash -- 如果为真(默认),则假定字典值表示命名空间(请参见 load_dict()
load_config(filename, **options)[源代码]

从中加载值 *.ini 样式配置文件。

配置文件由节组成,每个节由一个 [section] header, followed by key/value entries separated by either = or :. Section names and keys are case-insensitive. Leading and trailing whitespace is removed from keys and values. Values can be omitted, in which case the key/value delimiter may also be left out. Values can also span multiple lines, as long as they are indented deeper than the first line of the value. Commands are prefixed by `` “或”或 ; 只能单独出现在空行上。

节名和键名都可以包含点 (. )作为命名空间分隔符。实际的配置参数名是通过将节名和键名连接在一起并转换为小写来构造的。

特别部分 bottleROOT 请参阅根命名空间和 DEFAULT 节定义所有其他节的默认值。

使用python 3,可以启用扩展字符串插值。

参数:
  • filename -- 配置文件的路径或路径列表。
  • options -- 所有关键字参数都传递到基础 configparser.ConfigParser 构造函数调用。
load_dict(source, namespace='')[源代码]

从字典结构加载值。嵌套可用于表示命名空间。

>>> c = ConfigDict()
>>> c.load_dict({'some': {'namespace': {'key': 'value'} } })
{'some.namespace.key': 'value'}
update(*a, **ka)[源代码]

如果第一个参数是字符串,则所有键都以该命名空间为前缀。除此之外,它和通常的dict.update()一样工作。

>>> c = ConfigDict()
>>> c.update('some.namespace', key='value')
setdefault(k[, d]) → D.get(k,d), also set D[k]=d if k not in D[源代码]
meta_get(key, metafield, default=None)[源代码]

返回键的元字段的值。

meta_set(key, metafield, value)[源代码]

将键的元字段设置为新值。

meta_list(key)[源代码]

返回为键定义的元字段名的iterable。