Python ConfigParser: упрощение файлов конфигурации

ConfigParser является обязательным условием, если вы хотите создавать проекты Python, устойчивые к обновлениям и простые в управлении.

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

Давайте научимся использовать configparser!

Что такое модуль Python ConfigParser?

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

Файлы конфигурации хранят пары «ключ-значение», которые считываются приложением при запуске и используются как часть его логики.

ConfigParser — это модуль Python, позволяющий создавать файлы конфигурации простым способом. С помощью ConfigParser вы также можете читать или обновлять содержимое файла конфигурации. Структура файлов конфигурации, созданных с помощью ConfigParser, похожа на структуру файлов INI Microsoft Windows.

Отделение конфигурации от кода избавит вас от необходимости компилировать и повторно развертывать код с нуля только для того, чтобы внести изменения в конфигурацию.

Как узнать, установлен ли модуль ConfigParser?

Откройте оболочку Python и импортируйте модуль configparser.

Если вы не видите никаких ошибок, как в примере ниже, это означает, что модуль configparser установлен.

$ python
Python 3.8.5 (default, Sep  4 2020, 02:22:02) 
[Clang 10.0.0 ]:: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import configparser
>>>

А вот исключение, которое вы увидите (ModuleNotFoundError), если configparser не установлен:

>>> import configparser
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'configparser'

Как написать файл конфигурации INI с помощью Python ConfigParser

Давайте рассмотрим простой файл конфигурации следующим образом. Сохраните его на своем компьютере в файле с именем sample_config.ini.

[DEFAULT]
serverthreads = 45
content_type = text/html
content_length = 1024
autoscaling = no

[website_name.org]
username = your_name
login_mail = your_mail

[private.data.com]
password = secret_password
autoscaling = yes

В файлах конфигурации вы увидите имя раздела в квадратных скобках. Разделы являются основой файлов конфигурации.

В каждом разделе пары ключ-значение разделяются символом назначения ‘=’. Каждое ключевое значение должно быть уникальным в каждом разделе.

Давайте теперь проверим, как создать этот файл конфигурации с помощью configparser:

import configparser

config = configparser.ConfigParser()

# define sections much like a dictionary
config['DEFAULT'] = { 'serverthreads': 45, 'content_type': 'text/html', 'content_length': 1024 }

# we can define the key-value pairs later on as well
config['DEFAULT']['autoscaling'] = 'no'

config['website_name.org'] = dict()
config['website_name.org']['Username'] = 'your_name' 
config['website_name.org']['login_mail'] = 'your_mail'

config['private.data.com'] = {}
private = config['private.data.com']
private['Password'] = 'secret_password'
private['autoscaling'] = 'yes'

# finally, write the config object to an INI file
with open('generated_config.ini', 'w') as configfile:
    config.write(configfile)

Обратите внимание, что мы используем оператор Python with open для создания файла конфигурации с именем generated_config.ini.

Запустите программу Python на своем компьютере и убедитесь, что сгенерированный ею файл имеет те же свойства, что и исходный файл конфигурации, созданный нами в начале этого руководства.

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

Как видно из примера в предыдущем разделе, с файлом конфигурации можно работать так же, как со словарем.

Однако важно заметить разницу…

Все ключи в разделе конфигурации нечувствительны к регистру: вы можете легко убедиться в этом, проверив, что оба следующих выражения возвращают логическое значение True.

Вы можете добавить следующий код в конец предыдущего кода Python, который генерирует файл конфигурации.

print('ServerThreads' in config['DEFAULT'])
print('serverthreads' in config['DEFAULT'])

[output]
True
True

Далее в этом уроке я покажу вам, как читать INI-файл после его создания.

Другим аспектом, который следует учитывать, является то, что раздел DEFAULT предоставляет значения по умолчанию для всех остальных разделов.

Давайте проверим это, выведя значение свойства, определенного в разделе DEFAULT, но не определенного во втором разделе нашего файла конфигурации:

print(config['website_name.org']['content_type'])

[output]
text/html

Оно работает!

Еще одна важная вещь, которую следует помнить: вы не можете удалить раздел DEFAULT, попытка сделать это вызовет исключение ValueError:

config.pop('DEFAULT')

[output]
Traceback (most recent call last):
  File "configparser_test.py", line 26, in <module>
    config.pop('DEFAULT')
  File "/opt/anaconda3/lib/python3.8/_collections_abc.py", line 801, in pop
    del self[key]
  File "/opt/anaconda3/lib/python3.8/configparser.py", line 978, in __delitem__
    raise ValueError("Cannot remove the default section.")
ValueError: Cannot remove the default section.

Как прочитать файл конфигурации INI с помощью Python ConfigParser

Теперь, когда мы знаем, как создать файл конфигурации, пришло время научиться читать файл конфигурации.

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

Вы можете просто начать с инициализации анализатора конфигурации. Обратите внимание, что без чтения какого-либо файла конфигурации объект конфигурации возвращает пустой список разделов.

>>> import configparser
>>> config = configparser.ConfigParser()
>>> config.sections()
[]
>>>

Теперь используйте метод read объекта конфигурации, чтобы прочитать содержимое созданного нами файла конфигурации:

>>> config.read('generated_config.ini')
['generated_config.ini']

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

>>> config.sections()
['website_name.org', 'private.data.com']

Давайте выполним несколько операторов в файле конфигурации после его считывания из INI-файла:

>>> 'unknown_property' in config
False
>>>
>>> 'your_name' in config['website_name.org']['username']
True
>>>
>>> config['private.data.com']['password']
'secret_password'
>>>
>>> for key in config['DEFAULT']:
...     print(key)
... 
serverthreads
content_type
content_length
autoscaling

Вы, возможно, уже заметили, что…

Анализатор конфигурации использует строковый тип данных для значений в нашем файле конфигурации.

Функция type() ниже показывает, что значение, которое мы извлекаем из файла конфигурации, является строкой:

>>> config['DEFAULT']['serverthreads']
'45'
>>> type(config['DEFAULT']['serverthreads'])
<class 'str'>

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

>>> int(config['DEFAULT']['serverthreads'])
45

Однако в configparser есть очень удобный метод getboolean, который может различать логические значения в виде «да»/«нет», «вкл»/«выкл», «истина»/«ложь» и «1»/«0»:

>>> config['private.data.com'].getboolean('autoscaling')
True

Как получить значения из файла конфигурации с помощью ConfigParser

Аналогично словарю, вы можете использовать метод get() для получения значения, соответствующего ключу.

>>> website = config['website_name.org']
>>> website.get('login_mail')
'your_mail'

Более того, метод get() также допускает резервное значение, которое представляет собой значение, возвращаемое, если запрошенный ключ не найден в разделе:

>>> website.get('login_date', fallback='No login_date found')
'No login_date found'

Важно отметить, что раздел DEFAULT имеет иерархическое превосходство по сравнению с другими разделами, и значение, соответствующее ключу в разделе DEFAULT, будет иметь приоритет над резервным значением:

>>> website.get('content_type', fallback='No login_date found')
'text/html'

Обновление значений в файле конфигурации с помощью Python ConfigParser

Само собой разумеется, что также можно обновить имена ключей внутри файла конфигурации с помощью configparser:

>>> import configparser
>>> config = configparser.ConfigParser()
>>> config.read('generated_config.ini')
['generated_config.ini']
>>> config['private.data.com']['password'] = 'new_password'
>>> config['website_name.org']['login_date'] = 'new_date'
>>> config['new_section'] = {'user_port': 4098, 'user_request': 'yes'}
>>> 
>>> with open('generated_config.ini', 'w') as configfile:
...     config.write(configfile)
... 
>>>

Убедитесь, что содержимое файла конфигурации обновлено, как показано ниже:

[DEFAULT]
serverthreads = 45
content_type = text/html
content_length = 1024
autoscaling = no

[website_name.org]
username = your_name
login_mail = your_mail
login_date = new_date

[private.data.com]
password = new_password
autoscaling = yes

[new_section]
user_port = 4098
user_request = yes

Имеет ли это смысл?

Заключение

В этом уроке вы узнали:

  • Что такое файл конфигурации.
  • Как модуль Python configparser позволяет читать, записывать и обновлять файлы конфигурации.

Благодаря configparser вы теперь знаете, как упростить управление конфигурацией своих приложений.

Автор

Фото аватара

Владимир Михайлов

Программист на Python с большим количеством опыта и разнообразных проектов.