Python module config file

Конфигурационные файлы в Python

Конфиги. Все хранят их по разному. Кто-то в .yaml , кто-то в .ini , а кто-то вообще в исходном коде, подумав, что «Путь Django» с его settings.py действительно хорош.

В этой статье, я хочу попробовать найти идеальный (вероятнее всего) способ хранения и использования конфигурационных файлов в Python. Ну, а также поделиться своей библиотекой для них 🙂

Попытка №1

А что насчёт того чтобы хранить конфигурацию в коде? Ну, а что, вроде удобно, да и новых языков не придётся изучать. Существует множество проектов, в которых данный способ используется, и хочу сказать, вполне успешно.

Типичный конфиг в этом стиле выглядит так:

# settings.py TWITTER_USERNAME="johndoe" TWITTER_PASSWORD="johndoespassword" TWITTER_TOKEN=". "

Выглядит неплохо. Только одно настораживает, почему секьюрные данные хранятся в коде? Как мы это коммитить будем? Загадка. Разве что вносить наш файл в .gitignore , но это, конечно, вообще не решение.

Да и вообще, почему хоть какие-то данные хранятся в коде? Как мне кажется код, он на то и код, что должен выполнять какую-то логику, а не хранить данные.

Данный подход, на самом деле используется много где. В том же Django. Все думают, что раз это самый популярный фреймворк, который используется в самом Инстаграме, то они то уж плохое советовать не будут. Жаль, что это не так.

Попытка №2

Ладно, раз уж мы решили, что хранить данные в коде — не круто, то давайте искать альтернативу. Для конфигурационных файлов изобретено немалое количество различных форматов, в последнее время набирают большую популярность toml .

Но мы начнём с того, что нам предлагает сам Python — .ini . В стандартной библиотеке имеется библиотека configparser .

Наш конфиг, который мы уже писали ранее:

# settings.ini [Twitter] username="johndoe" password="johndoespassword" token=". "

А теперь прочитаем в Python:

import configparser # импортируем библиотеку config = configparser.ConfigParser() # создаём объекта парсера config.read("settings.ini") # читаем конфиг print(config["Twitter"]["username"]) # обращаемся как к обычному словарю! # 'johndoe'

Все проблемы решены. Данные хранятся не в коде, доступ прост. Но… а если нам нужно читать другие конфиги, ну там json или yaml например, или все сразу. Конечно, есть json в стандартной библиотеке и pyyaml , но придётся написать кучу (ну, или не совсем) кода для этого.

Читайте также:  Setname method in java

Попытка №3

А сейчас, я хотел бы показать Вам свою библиотеку, которая призвана решить все эти проблемы (ну, или хотя бы уменьшить ваши страдания :)).

Называется она betterconf и доступна на PyPi.

Установка так же проста, как и любой другой библиотеки:

Изначально, наш конфиг представлен в виде класса с полями:

# settings.py from betterconf import Config, field class TwitterConfig(Config): # объявляем класс, который наследуется от `Config` username = field("TWITTER_USERNAME", default="johndoe") # объявляем поле `username`, если оно не найдено, выставляем стандартное password = field("TWITTER_PASSWORD", default="johndoespassword") # аналогично token = field("TWITTER_TOKEN", default=lambda: raise RuntimeError("Account's token must be defined!") # делаем тоже самое, но при отсутствии токенавозбуждаем ошибку cfg = TwitterConfig() print(cfg.username) # 'johndoe'

По умолчанию, библиотека пытается взять значения из переменных окружения, но мы также можем настроить и это:

from betterconf import Config, field from betterconf.config import AbstractProvider import json class JSONProvider(AbstractProvider): # наследуемся от абстрактного класса SETTINGS_JSON_FILE = "settings.json" # путь до файла с настройками def __init__(self): with open(self.SETTINGS_JSON_FILE, "r") as f: self._settings = json.load(f) # открываем и читаем def get(self, name): return self._settings.get(name) # если значение есть - возвращаем его, иначе - None. Библиотека будет выбрасывать свою исключением, если получит None. provider = JSONProvider() class TwitterConfig(Config): username = field("twitter_username", provider=provider) # используем наш способ получения данных # . cfg = TwitterConfig() # . 

Из этого примера следует, что мы можем применять различные провайдеры для получения данных. И это действительно иногда бывает удобно, говорю из личного опыта.

Хорошо, а что если у нас в конфигах есть булевые значения, или числа, они же в итоге будут все равно приходить в строках. И для этого есть решение:

from betterconf import Config, field # из коробки доступно всего 2 кастера from betterconf.caster import to_bool, to_int class TwitterConfig(Config): # . post_tweets = field("TWITTER_POST_TWEETS", caster=to_bool) # . 

Таким образом, все похожие на булевые типы значения (а именно true и false будут преобразованы в питоновский bool . Регистр не учитывается.

Читайте также:  Check ssl with php

Свой кастер написать также легко:

from betterconf.caster import AbstractCaster class DashToDotCaster(AbstractCaster): def cast(self, val): return val.replace("-", ".") # заменяет тире на точки to_dot = DashToDotCaster() # . 

Итоги

Таким образом, мы пришли к выводу, что хранить настройки в исходных кодах — не есть хорошо. Для этого уже придуманы различные форматы. Ну, а вы познакомились с ещё одной полезной (как я считаю :)) библиотекой.

P.S

Да, также можно было включить и Pydantic , но я считаю, что он слишком НЕлегковесный для таких задач.

Источник

ConfigParser в Python — как его использовать?

Файлы конфигурации используются как пользователями, так и программистами. Как правило, их используют для хранения настроек вашего приложения, или операционной системы. Библиотека в ядре Python включает в себя модуль, под названием configparser, который вы можете использовать для создания и работы с файлами конфигурации. Что ж, давайте выделим несколько минут на то, чтобы узнать, как это работает.

Совместимость с Python 3

Из за нововведений в стандарте PEP 8 модуль ConfigParser в Python 3 был переименован в configparser. Возможные ошибки:
ImportError: no module named ConfigParser

Решение проблемы совместимости

Создание файла

Создание файла config при помощи configparser невероятно просто. Давайте напишем небольшой код, чтобы посмотреть, как это работает:

Данный код создает файл config с одной секцией, под названием Settings, которая будет содержать наши опции: font, font_size, font_style и font_info. Обратите внимание на то, что в Python 3 нам нужно указать, что мы пишем файл в режиме write-only, или “w”. А в Python 2.7, мы использовали “wb” для написания в бинарном режиме.

Как читать, обновлять и удалять опции

Теперь мы готовы к тому, что бы научиться чтению файла config, обновлять его опции и даже удалять их. В нашем случае учиться будет намного проще, если мы попробуем на практике написать какой-нибудь код. Просто добавьте следующую функцию в код, который вы писали ранее.

Этот код сначала проверяет, существует ли файл config в принципе. Если его нет, то он использует созданную нами ранее функцию createConfig, чтобы создать файл. Далее мы создаем объект ConfigParser и указываем путь к файлу config для чтения. Чтобы прочесть опцию в вашем config файле, мы вызываем метод нашего объекта ConfigParser, указываем ему наименование секции и опции.

Читайте также:  Знакомство с GET-запросами

Есть вопросы по Python?

На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!

Telegram Чат & Канал

Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!

Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!

Это вернет значение параметра. Если вы хотите изменить значение опции, вам нужно использовать метод set, в котором вы указываете название секции, опции, и новое значение. Наконец, мы можем использовать метод remove_option, чтобы удалить опцию. В нашем примере мы изменили значение font_size, и задали ему размер 12, затем мы удалили опцию font_style. После этого мы записали наши изменения на диск. Этот пример на на столько хорош, давайте упростим наш код. Для этого мы разделим наш код на на несколько функции:

Этот пример выглядит более организованно, по сравнению с первым. Я зашел так далеко, что назвал функции соответственно стандартам PEP8. Каждая функция должна объяснять сама себя и выполнять лишь одну задачу. Вместо того, чтобы помещать всю логику в одну единственную функцию, мы разделяем её на несколько функций, после чего демонстрируем их функционал в конце оператора if. Теперь вы можете импортировать модуль и использовать по назначению. Обратите внимание на то, что в этом примере есть сложная секция, так что вам, возможно, захочется усовершенствовать этот пример в дальнейшем, чтобы сделать его более универсальным.

Как использовать интерполяцию

Модуль configparser также подразумевает возможность интерполяции, что значит, что вы можете использовать существующие опции, для создания другой опции. Мы на самом деле это делали с опцией font_info, чьи параметры основаны на опциях font и font_size. Мы можем изменить интерполированное значение при помощи словаря Python. Давайте уделим несколько минут, и взглянем на оба случая.

Источник

Оцените статью