Этот модуль поможет сильно упростить использование конфигурационных
файлов, вы предпочитаете хранить константы и
настройки в .yaml
, .json
или в переменных окружения?
Это не важно, bestconfig
учитывает множество вариантов
и предоставляет очень удобный интерфейс доступа к данным
pip install bestconfig
Предположим, у вас такая структура проекта
root/
app:
main.py
myconfig.json
config.yaml
.env
app/main.py
from bestconfig import Config
config = Config("myconfig.json")
# На этом вся настройка закончилась
# В аргументах можно передать имена файлов,
# в которых у вас хранятся настройки, если они нестандартные
# Следующие варианты эквивалентны
logger = config.get('logger')
logger = config.logger
logger = config['logger']
mode = config.logger.mode
mode = config.get('logger.mode') # -> DEBUG или None
mode = config['__unknown__'] # raise KeyError
mode = config.get('__unknown__') # return None
Содержимое файлов:
.env
DATABASE_PASSWOD=postgres
config.yaml
HOST: http://localhost
PORT: 5050
logger:
mode: WARNING
myconfig.json
{
"VERSION": "1.23.4",
"BUILD": 5563
}
config.to_dict()
покажет следующее:
{
"logger": {
"mode": "DEBUG"
},
"VERSION": "1.23.4",
"BUILD": 5563,
"PORT": 5050,
"HOST": "http://localhost",
"DATABASE_PASSWOD": "postgres"
}
- Класс
Config
просканировал текущую директорию, вплоть до корня проекта - Нашел все указанные в аргументах файлы и те, что в списке по умолчанию
(например
.env
,env_file
,config.yaml
,configuration.ini
и тд)
- Файлы следующих типов:
.json
.yaml
.yml
.ini
.py
(если в нем нет инициализацииConfig()
во избежание рекурсии).cfg
- Файлы в формате
CONFIG_NAME=CONFIG_VALUE
- Уже существующие и новые переменные окружения
- Обычные
python
словари
-
Все комбинации имени
config
configuration
settings
setting
conf
и расширения
.json
.yaml
.ini
.env
.cfg
-
Выделенные, часто используемые названия
env_file
.env
config.py
- Через точку
config.name
- Нотация
python dict
config['name']
Бросает исключение при отсутствии config.get('name', 'default_value', raise_absent=False)
config.get('name.subname')
если параметр это тоже словарь, к вложенным значениям можно обращаться единым запросом черезget
, вложенность не ограничена- Можно сразу при запросе приводить результат к определенному типу
Эти функции, вернут вам значение соответствующего типа, либо, если преобразование не удалось -
config = Config() LIMIT = config.int('LIMIT') RATE = config.float('RATE') LOGGER = config.dict('logger') USERNAME = config.str('ADMIN_USERNAME') PRICES = config.list('PRICES')
None
- По умолчанию, при обращении без указания типа, происходит следующее
- Каждый формат файлов, например
.yaml
уже парсится с учетом типов, такvarname: 123
будет считано как число 123 - Если значение все равно представляет собой строку,
совершается попытка интерпретировать его
python
выражение, так.env
файл, содержащийLIST=[1, 2]
станетЧтобы избежать такого поведения, используйтеl = config.get('LIST') isinstance(l, list) # True print(l) # [1, 2]
Возвращенное значение не будет обработано, на самом деле, эта функция всего лишь делаетconfig.get_raw('key')
config.get(cast=None)
. За подробностями в исходники ;)
- Каждый формат файлов, например
Сохранить новую переменную, можно с помощью set
config.set('pages_limit', 12)
print(config.get('pages_limit')) -> 12
config.set('d', {'a': 'value'})
# config.d.a == 'value'
Чтобы проверить, что нужные переменные окружения или файлы
импортировались, используйте config.assert_contains()
config.set('key', 'value')
config.assert_contains('key') # pass
config.assert_contains('key1') # raise KeyError
Бывает необходимо некоторым образом преобразовать
конфиги после импорта из файлов, тогда пригодится функция update_from_locals()
from bestconfig import Config
config = Config()
FULL_NAME = f'{config.name} {config.lastname}'
config.update_from_locals()
Она рассматривает словарь locals()
(то есть локальные переменные) и добавляет в общую базу
config.get('FULL_NAME')
Также иногда бывает удобно, вместо config.set('key', 'value')
добавить целый словарь или даже файл во время исполнения
from bestconfig import Config
config = Config(exclude_default=True)
config.insert({
'name': 'Ivan'
})
config.assert_contains('name')
# Добавить к существующим еще и `other_file.yaml`
config.insert('other_file.yaml')
- github Ссылки ниже доступны только с гитхаба (не с pypi.org)
- Примеры использования
- Как запустить тесты
Если после документации остались вопросы, код подробно документирован, можно смело смотреть в исходники и читать docstring
- Поддержка загрузки из базы данных
- Поддержка загрузки с config сервера
- Перевод документации и комментариев на английский