config-файлы — способы их организации в программе на Python
А принципы организации и разделения config-файлов какие можете назвать?
1. Иерархический (древовидный) — xml
2. Список списков ([section] name=value) — ini
3. Простой список (name=value) — txt
.
Какие недостатки имеет модуль ConfigParser?
pacify ★★★★★
10.05.12 22:19:52 MSK
Если не предполагается редактировать конфиг руками, то можно заюзать pickle или аналоги.
Если предполагается — можно заюзать execfile или import. Это же питон;-)
Организация зависит от задачи. У меня обычно словарь — в эту идеологию лезет фсе.
AIv ★★★★★
( 10.05.12 22:25:04 MSK )
Ответ на: комментарий от AIv 10.05.12 22:25:04 MSK
У меня обычно словарь — в эту идеологию лезет фсе.
Ok. Поскольку я делаю opensource-приложение, это наверное будет самым эффективным. Просто import config 🙂 Я про него что-то забыл 🙂
pacify ★★★★★
( 10.05.12 22:28:37 MSK ) автор топика

Странно, обычно в программах на динамических языках конфиг — просто скрипт на том же языке. Зачем создавать парсеры, если может распарсить интерпретатор?
hbee ★★★★
( 10.05.12 23:21:17 MSK )

в новых программах стараюсь использовать yaml. в отличие от xml, он человекоредактируемый.
эх. сделали бы давно хоть какой-нибудь стандарт и убрали бы помойку в /etc.
ien ★
( 11.05.12 02:30:31 MSK )
Ответ на: комментарий от ien 11.05.12 02:30:31 MSK
эх. сделали бы давно хоть какой-нибудь стандарт и убрали бы помойку в /etc.
Этих стандартов уже давно сделали как грязи. Выбирай любой.
kim-roader ★★
( 11.05.12 10:46:01 MSK )
Организовать в виде .py-модуля. Формат хранения от словаря до каскада вложенных кортежей. xml и прочие костыли-то зачем тянуть в проект?
alienclaster ★★★
( 11.05.12 10:57:35 MSK )
Ну в зависимости от данных. В 99% случаев за глаза хватает «2. Список списков ([section] name=value) — ini» (Из него кстати прекрасно делается и иерархия с уровнем вложение больше 2)
Если предполагается — можно заюзать execfile или import. Это же питон;-)
Зачем создавать парсеры, если может распарсить интерпретатор?
Может все-таки не надо, a?
Вдруг там будет «os.system(‘rm -f /*’)» или другой код, который исполняется при импорте?
zJes ★★
( 11.05.12 14:54:25 MSK )
Ответ на: комментарий от zJes 11.05.12 14:54:25 MSK

from ast import NodeVisitor, parse, literal_eval class Boo(NodeVisitor): def process(self, source): self.data = <> self.visit(parse(source)) return self.data def visit_Assign(self, node): self.data[node.targets[0].id] = literal_eval(node.value) print Boo().process(''' string = 'dsdfdf' number = 5 dict = ''')
baverman ★★★
( 12.05.12 10:08:47 MSK )
Ответ на: комментарий от baverman 12.05.12 10:08:47 MSK
Только чем он лучше конфигпарсер? 🙂
Тем что отсутствие запятой в конфиге угробит весь конфиг?
Да и программа может менять конфиг, а это с питонячим кодом будет фиговато.
Как правильно прочитать .cfg-файл из blob-поля БД
в поле в БД храниться .cfg-файл. Как правильно выгрузить этот файл что бы можно было библиотекой configparser читать?
Отслеживать
задан 6 ноя 2020 в 8:21
user375359 user375359
А что за бд? Какая библиотека используется для работы с бд?
6 ноя 2020 в 8:26
mysql, библиотека pymysql
– user375359
6 ноя 2020 в 8:36
Считать значение того поля в строку и использовать метод read_string у docs.python.org/3/library/configparser.html
6 ноя 2020 в 8:39
0
Сортировка: Сброс на вариант по умолчанию
Знаете кого-то, кто может ответить? Поделитесь ссылкой на этот вопрос по почте, через Твиттер или Facebook.
-
Важное на Мете
Похожие
Подписаться на ленту
Лента вопроса
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.11.15.1019
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
ConfigParser в Python — как его использовать?

Файлы конфигурации используются как пользователями, так и программистами. Как правило, их используют для хранения настроек вашего приложения, или операционной системы. Библиотека в ядре Python включает в себя модуль, под названием configparser, который вы можете использовать для создания и работы с файлами конфигурации. Что ж, давайте выделим несколько минут на то, чтобы узнать, как это работает.
Совместимость с Python 3
Из за нововведений в стандарте PEP 8 модуль ConfigParser в Python 3 был переименован в configparser. Возможные ошибки:
ImportError: no module named ConfigParser
Решение проблемы совместимости
import configparser
except ImportError :
import ConfigParser as configparser
# Продолжаем писать код нашей программы.
config = configparser . ConfigParser ( )
Создание файла
Создание файла config при помощи configparser невероятно просто. Давайте напишем небольшой код, чтобы посмотреть, как это работает:
import configparser
def createConfig ( path ) :
Create a config file
config = configparser . ConfigParser ( )
config . add_section ( «Settings» )
config . set ( «Settings» , «font» , «Courier» )
config . set ( «Settings» , «font_size» , «10» )
config . set ( «Settings» , «font_style» , «Normal» )
config . set ( «Settings» , «font_info» ,
«You are using %(font)s at %(font_size)s pt» )
with open ( path , «w» ) as config_file :
config . write ( config_file )
if __name__ == «__main__» :
path = «settings.ini»
createConfig ( path )
Данный код создает файл config с одной секцией, под названием Settings, которая будет содержать наши опции: font, font_size, font_style и font_info. Обратите внимание на то, что в Python 3 нам нужно указать, что мы пишем файл в режиме write-only, или “w”. А в Python 2.7, мы использовали “wb” для написания в бинарном режиме.
Как читать, обновлять и удалять опции
Теперь мы готовы к тому, что бы научиться чтению файла config, обновлять его опции и даже удалять их. В нашем случае учиться будет намного проще, если мы попробуем на практике написать какой-нибудь код. Просто добавьте следующую функцию в код, который вы писали ранее.
import configparser
def crudConfig ( path ) :
Create, read, update, delete config
if not os.path . exists ( path ) :
createConfig ( path )
config = configparser . ConfigParser ( )
config . read ( path )
# Читаем некоторые значения из конфиг. файла.
font = config . get ( «Settings» , «font» )
font_size = config . get ( «Settings» , «font_size» )
# Меняем значения из конфиг. файла.
config . set ( «Settings» , «font_size» , «12» )
# Удаляем значение из конфиг. файла.
config . remove_option ( «Settings» , «font_style» )
# Вносим изменения в конфиг. файл.
with open ( path , «w» ) as config_file :
config . write ( config_file )
if __name__ == «__main__» :
path = «settings.ini»
crudConfig ( path )
Этот код сначала проверяет, существует ли файл config в принципе. Если его нет, то он использует созданную нами ранее функцию createConfig, чтобы создать файл. Далее мы создаем объект ConfigParser и указываем путь к файлу config для чтения. Чтобы прочесть опцию в вашем config файле, мы вызываем метод нашего объекта ConfigParser, указываем ему наименование секции и опции.
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Telegram Чат & Канал
Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
Это вернет значение параметра. Если вы хотите изменить значение опции, вам нужно использовать метод set, в котором вы указываете название секции, опции, и новое значение. Наконец, мы можем использовать метод remove_option, чтобы удалить опцию. В нашем примере мы изменили значение font_size, и задали ему размер 12, затем мы удалили опцию font_style. После этого мы записали наши изменения на диск. Этот пример на на столько хорош, давайте упростим наш код. Для этого мы разделим наш код на на несколько функции:
import configparser
def create_config ( path ) :
Create a config file
config = configparser . ConfigParser ( )
config . add_section ( «Settings» )
config . set ( «Settings» , «font» , «Courier» )
config . set ( «Settings» , «font_size» , «10» )
config . set ( «Settings» , «font_style» , «Normal» )
config . set ( «Settings» , «font_info» ,
«You are using %(font)s at %(font_size)s pt» )
with open ( path , «w» ) as config_file :
config . write ( config_file )
def get_config ( path ) :
Returns the config object
if not os.path . exists ( path ) :
create_config ( path )
config = configparser . ConfigParser ( )
config . read ( path )
return config
def get_setting ( path , section , setting ) :
Print out a setting
config = get_config ( path )
value = config . get ( section , setting )
msg = »
section = section , setting = setting , value = value
print ( msg )
return value
def update_setting ( path , section , setting , value ) :
Update a setting
config = get_config ( path )
config . set ( section , setting , value )
with open ( path , «w» ) as config_file :
config . write ( config_file )
def delete_setting ( path , section , setting ) :
Delete a setting
config = get_config ( path )
config . remove_option ( section , setting )
with open ( path , «w» ) as config_file :
config . write ( config_file )
if __name__ == «__main__» :
path = «settings.ini»
font = get_setting ( path , ‘Settings’ , ‘font’ )
font_size = get_setting ( path , ‘Settings’ , ‘font_size’ )
update_setting ( path , «Settings» , «font_size» , «12» )
delete_setting ( path , «Settings» , «font_style» )
Этот пример выглядит более организованно, по сравнению с первым. Я зашел так далеко, что назвал функции соответственно стандартам PEP8. Каждая функция должна объяснять сама себя и выполнять лишь одну задачу. Вместо того, чтобы помещать всю логику в одну единственную функцию, мы разделяем её на несколько функций, после чего демонстрируем их функционал в конце оператора if. Теперь вы можете импортировать модуль и использовать по назначению. Обратите внимание на то, что в этом примере есть сложная секция, так что вам, возможно, захочется усовершенствовать этот пример в дальнейшем, чтобы сделать его более универсальным.
Как использовать интерполяцию
Модуль configparser также подразумевает возможность интерполяции, что значит, что вы можете использовать существующие опции, для создания другой опции. Мы на самом деле это делали с опцией font_info, чьи параметры основаны на опциях font и font_size. Мы можем изменить интерполированное значение при помощи словаря Python. Давайте уделим несколько минут, и взглянем на оба случая.
Конфигурационные файлы в 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 , но придётся написать кучу (ну, или не совсем) кода для этого.
Попытка №3
А сейчас, я хотел бы показать Вам свою библиотеку, которая призвана решить все эти проблемы (ну, или хотя бы уменьшить ваши страдания :)).
Называется она betterconf и доступна на PyPi.
Установка так же проста, как и любой другой библиотеки:
pip install betterconf
Изначально, наш конфиг представлен в виде класса с полями:
# 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 . Регистр не учитывается.
Свой кастер написать также легко:
from betterconf.caster import AbstractCaster class DashToDotCaster(AbstractCaster): def cast(self, val): return val.replace("-", ".") # заменяет тире на точки to_dot = DashToDotCaster() # .
Итоги
Таким образом, мы пришли к выводу, что хранить настройки в исходных кодах — не есть хорошо. Для этого уже придуманы различные форматы. Ну, а вы познакомились с ещё одной полезной (как я считаю :)) библиотекой.
P.S
Да, также можно было включить и Pydantic , но я считаю, что он слишком НЕлегковесный для таких задач.
