Parsing config file in python

Использование Python для парсинга файлов конфигурации

Перевод статьи «Use Python to parse configuration files».

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

Существует несколько популярных форматов файлов конфигурации. Среди них –

  • почтенный (хотя иногда недостаточно определенный) формат INI,
  • популярный, но иногда сложный для написания вручную формат JSON,
  • обширный, но иногда удивительный в деталях формат YAML
  • и новейшее дополнение TOML, о котором многие люди не слышали. Пока что.

Ваша первая задача – выбрать формат, а затем задокументировать этот выбор. Разобравшись с этой простой частью, можно заняться парсингом конфигурации.

Иногда рекомендуется иметь класс, соответствующий «абстрактным» данным в конфигурации. Поскольку этот код ничего не делает с конфигурацией, это самый простой способ показать логику парсинга с синтаксической точки зрения.

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

Абстрактное определение класса конфигурации может выглядеть примерно так:

from __future__ import annotations import attr @attr.frozen class Configuration: @attr.frozen class Files: input_dir: str output_dir: str files: Files @attr.frozen class Parameters: patterns: List[str] parameters: Parameters

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

def configuration_from_dict(details): files = Configuration.Files( input_dir=details["files"]["input-dir"], output_dir=details["files"]["output-dir"], ) parameters = Configuration.Paraneters( patterns=details["parameters"]["patterns"] ) return Configuration( files=files, parameters=parameters, )

JSON

JSON (JavaScript Object Notation) – это формат, подобный JavaScript.

Вот пример конфигурации в формате JSON:

json_config = """ < "files": < "input-dir": "inputs", "output-dir": "outputs" >, "parameters": < "patterns": [ "*.txt", "*.md" ] >> """

Логика парсинга «встраивает» JSON во встроенные структуры данных Python (словари, списки, строки) с помощью модуля json , а затем создает класс из словаря:

import json def configuration_from_json(data): parsed = json.loads(data) return configuration_from_dict(parsed)

INI

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

Вот такая конфигурация у нас получится на INI:

ini_config=""" [files] input-dir = inputs output-dir = outputs [parameters] patterns = ['*.txt', '*.md'] """

Python может парсить его с помощью встроенного модуля configparser . Парсер ведет себя как dict-подобный объект, поэтому его можно передать напрямую в configuration_from_dict :

import configparser def configuration_from_ini(data): parser = configparser.ConfigParser() parser.read_string(data) return configuration_from_dict(parser)

YAML

YAML (Yet Another Markup Language) – это расширение JSON, которое упрощает написание кода вручную. Отчасти это достигается за счет длинной спецификации.

Вот такая конфигурация будет в YAML:

yaml_config = """ files: input-dir: inputs output-dir: outputs parameters: patterns: - '*.txt' - '*.md' """

Чтобы Python запарсил это, вам необходимо установить сторонний модуль. Самый популярный — PyYAML ( pip install pyyaml ). Парсер YAML также возвращает встроенные типы данных Python, которые можно передать в configuration_from_dict . Однако YAML-парсер ожидает поток, поэтому вам нужно преобразовать строку в поток.

import io import yaml def configuration_from_yaml(data): fp = io.StringIO(data) parsed = yaml.safe_load(fp) return configuration_from_dict(parsed)

TOML

TOML (Tom’s Own Markup Language) разработан как легкая альтернатива YAML. Спецификация здесь короче. И такой формат уже кое-где популярен (например, менеджер пакетов Rust, Cargo, использует ее для конфигурации своих пакетов).

А вот так будет выглядеть наша конфигурация на TOML:

toml_config = """ [files] input-dir = "inputs" output-dir = "outputs" [parameters] patterns = [ "*.txt", "*.md",] """

Чтобы запарсить TOML, вам необходимо установить сторонний пакет. Самый популярный из них называется просто toml . Он возвращает базовые типы данных Python.

import toml def configuration_from_toml(data): parsed = toml.loads(data) return configuration_from_dict(parsed)

Заключение

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

Источник

Use Python to parse configuration files

Python programming language logo with question marks

Sometimes, a program needs enough parameters that putting them all as command-line arguments or environment variables is not pleasant nor feasible. In those cases, you will want to use a configuration file.

There are several popular formats for configuration files. Among them are the venerable (although occasionally under-defined) INI format, the popular but sometimes hard to write by hand JSON format, the extensive yet occasionally surprising in details YAML format, and the newest addition, TOML , which many people have not heard of yet.

Your first task is to choose a format and then to document that choice. With this easy part out of the way, it is time to parse the configuration.

It is sometimes a good idea to have a class that corresponds to the «abstract» data in the configuration. Because this code will do nothing with the configuration, this is the simplest way to show parsing logic.

Imagine the configuration for a file processor: it includes an input directory, an output directory, and which files to pick up.

The abstract definition for the configuration class might look something like:

from __future__ import annotations
import attr @attr.frozen class Configuration: @attr.frozen class Files: input_dir: str output_dir: str files: Files @attr.frozen class Parameters: patterns: List[str] parameters: Parameters

To make the format-specific code simpler, you will also write a function to parse this class out of dictionaries. Note that this assumes the configuration will use dashes, not underscores. This kind of discrepancy is not uncommon.

def configuration_from_dict(details): files = Configuration.Files( input_dir=details["files"]["input-dir"], output_dir=details["files"]["output-dir"], ) parameters = Configuration.Paraneters( patterns=details["parameters"]["patterns"] ) return Configuration( files=files, parameters=parameters, )

JSON

JSON (JavaScript Object Notation) is a JavaScript-like format.

Here is an example configuration in JSON format:

json_config = """ < "files": < "input-dir": "inputs", "output-dir": "outputs" >, "parameters": < "patterns": [ "*.txt", "*.md" ] >> """

The parsing logic parses the JSON into Python’s built-in data structures (dictionaries, lists, strings) using the json module and then creates the class from the dictionary:

import json def configuration_from_json(data): parsed = json.loads(data) return configuration_from_dict(parsed)

INI

The INI format, originally popular on Windows, became a de facto configuration standard.

Here is the same configuration as an INI:

ini_config=""" [files] input-dir = inputs output-dir = outputs [parameters] patterns = ['*.txt', '*.md'] """

Python can parse it using the built-in configparser module. The parser behaves as a dict -like object, so it can be passed directly to configuration_from_dict :

import configparser def configuration_from_ini(data): parser = configparser.ConfigParser() parser.read_string(data) return configuration_from_dict(parser)

YAML

YAML (Yet Another Markup Language) is an extension of JSON that is designed to be easier to write by hand. It accomplishes this, in part, by having a long specification.

Here is the same configuration in YAML:

yaml_config = """ files: input-dir: inputs output-dir: outputs parameters: patterns: - '*.txt' - '*.md' """

For Python to parse this, you will need to install a third-party module. The most popular is PyYAML ( pip install pyyaml ). The YAML parser also returns built-in Python data types that can be passed to configuration_from_dict . However, the YAML parser expects a stream, so you need to convert the string into a stream.

import io import yaml def configuration_from_yaml(data): fp = io.StringIO(data) parsed = yaml.safe_load(fp) return configuration_from_dict(parsed)

TOML

TOML (Tom’s Own Markup Language) is designed to be a lightweight alternative to YAML. The specification is shorter, and it is already popular in some places (for example, Rust’s package manager, Cargo, uses it for package configuration).

Here is the same configuration as a TOML:

toml_config = """ [files] input-dir = "inputs" output-dir = "outputs" [parameters] patterns = [ "*.txt", "*.md",] """

In order to parse TOML, you need to install a third-party package. The most popular one is called, simply, toml . Like YAML and JSON, it returns basic Python data types.

import toml def configuration_from_toml(data): parsed = toml.loads(data) return configuration_from_dict(parsed)

Summary

Choosing a configuration format is a subtle tradeoff. However, once you make the decision, Python can parse most of the popular formats using a handful of lines of code.

Computer screen with files or windows open

What is a config file?

There are several popular formats for configuration files, each with its own strengths. Find what works best for you.

Looking back with binoculars

Parse JSON config files with Groovy

Sidestep the debate on whether or not to use JSON as a configuration format and just learn how to parse it using Groovy.

bash logo on green background

Parsing config files with Bash

Separating config files from code enables anyone to change their configurations without any special programming skills.

Woman sitting in front of her computer

Parsing config files with Lua

Configure persistent application settings with the Lua programming language.

Источник

Читайте также:  Reloading page with php
Оцените статью