- jsonconfigreader 1.3.1
- Installation
- Usage
- Uploading project to PyPi
- Run unit tests (Example for Visual Studio)
- Generate docs and updating docs
- Использование Python для парсинга файлов конфигурации
- JSON
- INI
- YAML
- TOML
- Заключение
- python-json-config 1.2.3
- Навигация
- Ссылки проекта
- Статистика
- Метаданные
- Сопровождающие
- Классификаторы
- Описание проекта
- Overview
- Installing
- Usage
- Validate field types
- Validate field values
- Transform field values
- Define field access settings
- Access config values
- Change config values
- Overwrite fields with environment variables
- Serialization
jsonconfigreader 1.3.1
Utility that allows to read and parse json config files.
Possible to specify links to the default values in the config (See Usage section).
Installation
python -m pip install —upgrade pip setuptools wheel
pip install -r requirements.txt
Usage
Example of the config file:
C:\User\test\qa_hotfix_config.json < "defaults": < "dataBaseUrl": "http://db:5000" >, "dataBase1": "", "dataBase2": "" >
- Specify that lib in your project dependencies
- Import from jsonconfigparser.json_config_reader import JsonConfigReader
- Create an instance of the class passing config folder path and options
config_path = 'C:\User\test\qa_config.json' json_config_reader = JsonConfigReader(config_path) config = json_config_reader.get() file_path = json_config_reader.get_config_file_path() print(config['dataBase1']) print(file_path) >> http://db:5000 >> C:\User\test\qa_config.json
Uploading project to PyPi
python setup.py sdist upload -r
Run unit tests (Example for Visual Studio)
- From Visual Studio
- Click Test -> Run -> All Test
- View Test run in Test Explorer
- Navigate into project directory
- python -m unittest
Generate docs and updating docs
- Run easy_install -U sphinx
- Navigate to docs folder
- Run sphinx-quickstart
- Follow instruction
Использование 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 сможет справиться с парсингом большинства популярных форматов, при этом используя всего лишь несколько строк кода.
python-json-config 1.2.3
This library allows to load json configs and access the values like members (i.e., via dots), validate config field types and values and transform config fields.
Навигация
Ссылки проекта
Статистика
Метаданные
Лицензия: MIT License (MIT)
Требует: Python >=3.6
Сопровождающие
Классификаторы
Описание проекта
Overview
This library allows to load json configs and access the values like members (i.e., config.server.port instead of config[‘server’][‘port’] ), validate the data types of fields and transform the values of fields.
Installing
pip install python-json-config
Usage
from python_json_config import ConfigBuilder # create config parser builder = ConfigBuilder() # parse config config = builder.parse_config('path/to/config.json') # access elements host = config.server.host port = config.server.port myfield = config.myfield
Validate field types
builder.validate_field_type('server.ip', str) builder.validate_field_type('server.port', int) builder.validate_field_type('jwt.access_token_expires', str)
Validate field values
from python_json_config.validators import is_unreserved_port, is_ipv4_address, is_timedelta # use provided methods builder.validate_field_value('server.ip', is_ipv4_address) builder.validate_field_value('server.port', is_unreserved_port) builder.validate_field_value('jwt.access_token_expires', is_timedelta) # use custom validation function builder.validate_field_value('server.ip', lambda ip: ip != '0.0.0.0') # return custom error messages in your lambda builder.validate_field_value('server.ip', lambda ip: (ip != '0.0.0.0', 'IP is unroutable.')) # chain validation functions builder.validate_field_value('server.ip', [lambda ip: ip != 'localhost', lambda ip: ip != '127.0.0.1'])
Transform field values
from python_json_config.transformers import to_timedelta # use provided methods builder.transform_field_value('jwt.access_token_expires', to_timedelta) from datetime import datetime # parse a timedelta (e.g., Jun 1 2005) into a datetime object builder.transform_field_value('important_date', lambda date: datetime.strptime(date, '%b %d %Y'))
Define field access settings
# required means an error is thrown if a non-existing field is accessed builder.set_field_access_required() # return None for the following fields instead of throwing an error builder.add_optional_field('server.host') builder.add_optional_fields(['cache.ttl', 'server.path']) # optional means None is returned if a non-existing field is accessed builder.set_field_access_optional() # throw an error for the following fields instead of returning None builder.add_required_field('server.user') builder.add_required_fields(['cache.backend', 'server.password'])
Access config values
port = config.server.port assert port > 1023 ip = config.server.ip assert ip not in ['0.0.0.0', 'localhost', '127.0.0.1'] important_date = config.important_date assert isinstance(important_date, datetime) jwt_access_token_expires = config.jwt.access_token_expires assert isinstance(jwt_access_token_expires, timedelta)
Change config values
config = ConfigBuilder().parse_config() config.add("server.host", "localhost") assert config.server.host == "localhost" config.add("cache", "redis") assert config.cache == "redis" config.update("server.port", 1025) assert config.server.port == 1025 config.update("server.user", "user", upsert=True) assert config.server.user == "user"
Overwrite fields with environment variables
First, set environment variables (e.g., via bash):
$ MYPROJECT_SERVER_HOST="localhost" $ MYPROJECT_CACHE="redis" $ MYPYTHONPROJECTS_USER="user"
Escape underscores in names of variables with another underscore:
$ MYPYTHONPROJECTS_LOG__FILE="project.log"
Then just tell the builder, which prefixes should be merged:
builder = ConfigBuilder() # you can also just pass a single prefix (builder.merge_with_env_variables("MYPROJECT") builder.merge_with_env_variables(["MYPROJECT", "MYPYTHONPROJECTS"]) config = builder.parse_config() assert config.server.host == "localhost" assert config.cache == "redis" assert config.user == "user" assert config.log_file == "project.log"
Alternatively you can also do the merging after creating the config object:
builder = ConfigBuilder() config = builder.parse_config() config.merge_with_env_variables(["MYPROJECT", "MYPYTHONPROJECTS"]) assert config.server.host == "localhost" assert config.cache == "redis" assert config.user == "user"
Serialization
The config can be serialized to a dictionary, json or binary (via pickle or msgpack).
builder = ConfigBuilder() config = builder.parse_config() import pickle pickle_config = pickle.loads(pickle.dumps(config)) dict_config = builder.parse_config(config.to_dict()) import json json_config = builder.parse_config(config.to_json()) import msgpack msgpack_config = Config.from_msgpack(config.to_msgpack())
Important note: serializing via json or msgpack will stringify any non-serializable value (e.g., datetime objects).