Package: bestconfig
bestconfigPython модуль для работы с файлами конфигурации проектаЭтот модуль поможет сильно упростить использование конфигурационных
файлов, вы предпочитаете хранить константы и
настройки в.yaml,.jsonили в переменных окружения?
Это не важно,bestconfigучитывает множество вариантов
и предоставляет очень удобный интерфейс доступа к даннымInstallationpip install bestconfigA Simple ExampleПредположим, у вас такая структура проектаroot/
    app:
      main.py
      myconfig.json
    config.yaml
    .envapp/main.pyfrombestconfigimportConfigconfig=Config("myconfig.json")# На этом вся настройка закончилась# В аргументах можно передать имена файлов,# в которых у вас хранятся настройки, если они нестандартные# Следующие варианты эквивалентныlogger=config.get('logger')logger=config.loggerlogger=config['logger']mode=config.logger.modemode=config.get('logger.mode')# -> DEBUG или Nonemode=config['__unknown__']# raise KeyErrormode=config.get('__unknown__')# return NoneСодержимое файлов:.envDATABASE_PASSWOD=postgresconfig.yamlHOST:http://localhostPORT:5050logger:mode:WARNINGmyconfig.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словариФайлы для поиска по умолчаниюВсе комбинации имениconfigconfigurationsettingssettingconfи расширения.json.yaml.ini.env.cfgВыделенные, часто используемые названияenv_file.envconfig.pyДоступ к даннымЧерез точкуconfig.nameНотацияpython dictconfig['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)# Trueprint(l)# [1, 2]Чтобы избежать такого поведения, используйтеconfig.get_raw('key')Возвращенное значение не будет обработано, на самом деле, эта функция всего лишь делаетconfig.get(cast=None). За подробностями в исходники ;)Сохранить новую переменную, можно с помощьюsetconfig.set('pages_limit',12)print(config.get('pages_limit'))->12config.set('d',{'a':'value'})# config.d.a == 'value'Чтобы проверить, что нужные переменные окружения или файлы
импортировались, используйтеconfig.assert_contains()config.set('key','value')config.assert_contains('key')# passconfig.assert_contains('key1')# raise KeyErrorБывает необходимо некоторым образом преобразовать
конфиги после импорта из файлов, тогда пригодится функцияupdate_from_locals()frombestconfigimportConfigconfig=Config()FULL_NAME=f'{config.name}{config.lastname}'config.update_from_locals()Она рассматривает словарьlocals()(то есть локальные переменные) и добавляет в общую базуconfig.get('FULL_NAME')Также иногда бывает удобно, вместоconfig.set('key', 'value')добавить целый словарь или даже файл во время исполненияfrombestconfigimportConfigconfig=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 сервераПеревод документации и комментариев на английский