Настройка (ЭСКИЗ)
Приложения Bottle могут хранить свою конфигурацию в Bottle.config, объекте, подобном словарю, и центральном месте для приложений. Этот словарь управляет многими аспектами фреймворка, сообщает (более новым) плагинам, что делать, и может использоваться для хранения собственной конфигурации.
Основы конфигурации
Объект Bottle.config ведет себя очень похоже на обычный словарь. Все стандартные методы словаря работают как ожидается. Давайте начнем с некоторых примеров:
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}
Объект приложения не всегда доступен, но пока вы находитесь в контексте запроса, вы можете использовать объект request для получения текущего приложения и его конфигурации:
from bottle import request
def is_admin(user):
return user == request.app.config['myapp.admin_user']
Конвенция именования
Для упрощения жизни, плагины и приложения должны придерживаться некоторых простых правил при именовании параметров конфигурации:
- Все ключи должны быть строками в нижнем регистре и следовать правилам идентификаторов Python (без специальных символов, кроме подчеркивания).
- Пространства имен разделяются точками (например,
namespace.fieldилиnamespace.subnamespace.field). - Bottle использует корневое пространство имен для собственной конфигурации. Плагины должны хранить все свои переменные в собственном пространстве имен (например,
sqlite.dbилиwerkzeug.use_debugger). - Ваше собственное приложение должно использовать отдельное пространство имен (например,
myapp.*).
Загрузка конфигурации из файла
Файлы конфигурации полезны, если вы хотите позволить не программистам настраивать ваше приложение, или просто не хотите вносить изменения в файлы Python-модулей, чтобы изменить порт базы данных. Очень распространенный синтаксис для файлов конфигурации показан здесь:
[bottle] debug = True [sqlite] db = /tmp/test.db commit = auto [myapp] admin_user = defnull
С помощью ConfigDict.load_config() вы можете загрузить эти файлы конфигурации в стиле *.ini с диска и импортировать их значения в существующую конфигурацию:
app.config.load_config('/etc/myapp.conf')
Загрузка конфигурации из вложенного словаря
Другой полезный метод — 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))
Прослушивание изменений конфигурации
Обработчик config в объекте приложения срабатывает каждый раз, когда значение в Bottle.config изменяется. Этот обработчик можно использовать для реагирования на изменения конфигурации во время выполнения, например, для повторного подключения к новой базе данных, изменения настроек отладки фонового сервиса или изменения пулов потоков-рабочих. Обработчик-обратный вызов получает два аргумента (ключ, новое_значение) и вызывается перед тем, как значение фактически изменится в словаре. Выброс исключения из обработчика-обратного вызова отменяет изменение, и старое значение сохраняется.
@app.hook('config')
def on_config_change(key, value):
if key == 'debug':
switch_own_debug_mode_to(value)
Обработчики-обратные вызовы не могут изменить значение, которое должно быть сохранено в словаре. Для этого предназначены фильтры.
Фильтры и другие метаданные
ConfigDict позволяет хранить метаданные вместе с ключами конфигурации. В настоящее время определены два поля метаданных:
- help
- Строка справки или описания. Может использоваться средствами отладки, интроспекции или администрирования для помощи системному администратору в настройке приложения.
- filter
- Вызываемый объект, который принимает и возвращает единственное значение. Если для ключа определен фильтр, любое новое значение, сохраненное для этого ключа, сначала передается через обратный вызов фильтра. Фильтр может использоваться для преобразования значения в другой тип, проверки на недействительные значения (выброс ValueError) или вызова побочных эффектов.
Эта функция наиболее полезна для плагинов. Они могут валидировать свои параметры конфигурации или вызывать побочные эффекты с помощью фильтров и документировать свою конфигурацию с помощью полей 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(*a, **ka)[source] -
Хранилище конфигурации, подобное словарю, с дополнительной поддержкой пространств имен, валидаторов, метаданных, слушателей изменений и т. д.
Это хранилище оптимизировано для быстрого доступа к чтению. Получение ключа или использование методов словаря, не изменяющих его (например,
dict.get()) не имеет накладных расходов по сравнению с обычным словарем.-
load_config(filename)[source] -
Загрузка значений из файла конфигурации в формате *.ini.
Если файл конфигурации содержит разделы, их имена используются в качестве пространств имен для значений внутри. Два специальных раздела
DEFAULTиbottleотносятся к корневому пространству имен (без префикса).
-
load_dict(source, namespace='', make_namespaces=False)[source] -
Импорт значений из структуры словаря. Вложение может быть использовано для представления пространств имен.
>>> ConfigDict().load_dict({'name': {'space': {'key': 'value'}}}) {'name.space.key': 'value'}
-
update(*a, **ka)[source] -
Если первый параметр является строкой, все ключи префиксруются этим пространством имен. В остальном он работает так же, как и обычный dict.update(). Пример:
update('some.namespace', key='value')
-
meta_get(key, metafield, default=None)[source] Возвращает значение поля метаданных для ключа.
-
meta_set(key, metafield, value)[source] Устанавливает поле метаданных для ключа в новое значение. Это запускает обработчик изменений для существующих ключей.
-
meta_list(key)[source] Возвращает итерируемый объект имен полей метаданных, определенных для ключа.
-
© 2009–2017 Marcel Hellkamp
Licensed under the MIT License.
https://bottlepy.org/docs/0.12/configuration.html