Найти в Дзене

Конфиг на базе TOML

В статье показывается взаимодействие с несколькими конфигами на базе TOML-разметки. Язык: Python 3.12 (на других версиях часть кода не будет работать) Библиотеки: Для начала создадим 2 файла с конфигами файл: db_con_p.toml [SQL_SERVER_DED] ded_host = "MSK_DEDUCTOR01RM" ded_name = "DEDUCTOR_P" [SQL_SERVER_LOG] lom_host = "MSK_LOGINOM02RM" lom_name = "LOGINOM_P" файл: web_con_p.toml [CRE] cre_host = "localhost" cre_pass = "123" cre_methods = "1,8,22" [CRONOS] crs_host = "localhost" crs_pass = "567" Теперь создадим питоновский файл Предполагаю, что библиотеки pydantic и pydantic_settings уже установлены. Пока пишем общую структуру классов файл: app.py Класс ConfigBase - это базовый конфиг для всех конфигов с расширением. Он наследуется от BaseSettings, а не от BaseModel, чтобы в рамках нашего конфига мы могли не только использовать объектную модель библиотеки pydantic, но производить дополнительные настройки для работы с TOML файлами. Классы SQL_SERVER_DED и SQL_SERVER_LOG - это класс
Оглавление

В статье показывается взаимодействие с несколькими конфигами на базе TOML-разметки.

Технологии

Язык: Python 3.12 (на других версиях часть кода не будет работать)

Библиотеки:

  • pydantic (для построения объектной модели, в рамках которой можно удобно валидировать данные)
  • pydantic_settings (помогает извлекать данные из toml файлов)
  • typing (для сокрытия чувствительных данных)

План работ

  • Подготовка toml файлов
  • Создаем простую сборку
  • Рефакторинг программы

Подготовка toml файлов

Для начала создадим 2 файла с конфигами

файл: db_con_p.toml

[SQL_SERVER_DED]
ded_host = "MSK_DEDUCTOR01RM"
ded_name = "DEDUCTOR_P"
[SQL_SERVER_LOG]
lom_host = "MSK_LOGINOM02RM"
lom_name = "LOGINOM_P"

файл: web_con_p.toml

[CRE]
cre_host = "localhost"
cre_pass = "123"
cre_methods = "1,8,22"
[CRONOS]
crs_host = "localhost"
crs_pass = "567"

Теперь создадим питоновский файл

Предполагаю, что библиотеки pydantic и pydantic_settings уже установлены.

Пока пишем общую структуру классов

файл: app.py

-2

Класс ConfigBase - это базовый конфиг для всех конфигов с расширением. Он наследуется от BaseSettings, а не от BaseModel, чтобы в рамках нашего конфига мы могли не только использовать объектную модель библиотеки pydantic, но производить дополнительные настройки для работы с TOML файлами.

Классы SQL_SERVER_DED и SQL_SERVER_LOG - это классы с данными из файлов. Пока в них нет данных, но мы скоро исправим. Они наследуются от ConfigBase, т.е. этим классам нужен будет объект settings_cls, который лежит в ConfigBase, а не в BaseSettings.

Класс Config - это финальный конфиг. В интернете можно встретить примеры, что данный класс наследуется от BaseSettings. В моем примере он наследуется от ConfigBase, чтобы также использовать settings_cls, который лежит в ConfigBase, а не в BaseSettings.

Создаем простую сборку

Укажем классу ConfigBase расположение файла TOML

-3

В классах SQL_SERVER_DED и SQL_SERVER_LOG создадим поля с типизацией.

-4

ВАЖНО:

  • Названия полей должно совпадать с теми, что лежат в файле db_con_p.toml
  • Название класса должно совпадать с названием структуры (в файле db_con_p.toml), в которую вложены поля.
  • В классе нужно указать все поля из структуры.
  • Необходимо создать классы под все структуры из файла.

В классе Config создаем переменные

-5

ВАЖНО:

  • Наименование переменных должно совпадать с названием классов
  • Переменным присваивается тип (типизация) конкретного класса

И так... если сейчас запустим класс Config, то ничего не заработает. Т.к. Config не умеет обрабатывать классы SQL_SERVER_DED и SQL_SERVER_LOG

Чтобы проблему решить, необходимо импортировать новый класс TomlConfigSettingsSource. И дополнительно импортируем для работы с типизацией Self и PydanticBaseSettingsSource

from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic_settings import TomlConfigSettingsSource, PydanticBaseSettingsSource
from typing import Self

И обновить новую логику в классе Config

-6

ВАЖНО:

  • Были добавлены классовые методы load и settings_customise_sources
  • Метод load можно назвать как угодно, хоть main
  • Метод settings_customise_sources мы переопределяем у класса BaseSettings
  • Метод load грузит наш конфиг в память программы из файла TOML
  • Метод load возвращает тип Config, но т.к. Config не существует внутри Config, мы можем через библиотеку typing вернуть тип Self. Т.е. себя же вернет, а если точнее, экземпляр класса. Это не то же самое, что вернуть класс, т.е. что мы хотели, но в рамках этой реализации мы не обращаем внимание на этот нюанс.
  • Метод settings_customise_sources мы переопределяем, чтобы наш класс Config научился понимать, как обрабатывать TOML файлы. Именно для этого метода мы наследуемся от ConfigBase, чтобы именно его settings_cls передавался в TomlConfigSettingsSource.

Можем запустить. Все работает.

-7

Результат:

-8

Полный код выглядит так:

-9

Рефакторинг программы

В рамках рефакторинга:

  • добавим обработку не одного, а двух файлов TOML
  • красиво оформим логики в разные файлы и папки

Первым делом давайте файлы TOML уберем в папку connections

-10

В файле app.py в классе ConfigBase заменим

SettingsConfigDict(toml_file="db_con_p.toml")

на

SettingsConfigDict(toml_file=("connections/db_con_p.toml","connections/web_con_p.toml"))

Сам класс перенесем в папку config\base в файл main.py

файл: main.py

-11

рядом создадим файл: __init__.py

from .main import ConfigBase
Расположение файлов после переноса ConfigBase
Расположение файлов после переноса ConfigBase

ВАЖНО:

В main.py прописываем

if __name__ == "__main__":
pass

т.к. намекаем, что данный файл не запускается как самостоятельный

Теперь из файла app.py перенесем классы SQL_SERVER_DED и SQL_SERVER_LOG в папку config\db в файл main.py

файл: main.py

-13

рядом создадим файл: __init__.py

from .main import SQL_SERVER_DED, SQL_SERVER_LOG

Теперь на примере классов SQL_SERVER_DED и SQL_SERVER_LOG напишем код для файла web_con_p.toml и расположим его в папке config\web в файле main.py.

Создадим классы CRE и CRONOS. В этих классах есть поля с паролями. Пароли необходимо скрыть для безопасности.

файл: main.py

-14

рядом создадим файл: __init__.py

from .main import CRE, CRONOS

Теперь из файла app.py перенесем класс Config в папку config в файл main.py.

И добавим в код новые поля для классов CRE и CRONOS

файл: main.py

-15

рядом создадим файл: __init__.py

from .main import Config

Финальное расположение файлов

-16

Осталось поправить код в корневом файле app.py

-17

На этом всё. Запускаем программу. Получаем результат:

-18

Особенности:

  • Класс Config не знает расположение TOML файлов, но умеет их обрабатывать
  • Чувствительные данные скрыты от юзеров, которые будут использоваться класс Config
  • Для каждого сервиса, БД и пр. можно по аналогии с примерами создавать свои TOML файлы с конфигурациями. Т.е. программа может работать с множеством конфигов

GitLab

Sign in · GitLab

Подписывайтесь на Дзен, а также приглашаю в мой телеграмм канал, там публикую другой, но не менее интересный контент.