Файл конфигурации со списком пар ключ-значение в python

У меня есть скрипт Python, который анализирует набор сообщений об ошибках и проверяет каждое сообщение, соответствует ли оно определенному шаблону (регулярному выражению), чтобы сгруппировать эти сообщения. Например, «файл x не существует» и «файл y не существует» будет соответствовать «файл .* не существует» и будет учитываться как два вхождения категории «файл не найден».

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

Я бы хотел, чтобы этот файл можно было редактировать вручную, поэтому я отказываюсь от любой формы двоичной сериализации, а также я бы предпочел не прибегать к сериализации xml, чтобы избежать проблем с экранированием символов (& ‹> и так далее... ).

Есть ли у вас какие-либо идеи о том, что может быть хорошим способом добиться этого?

Обновление: спасибо Дарену Томасу и Федерико Рампони, но у меня не может быть внешнего файла Python с, возможно, произвольным кодом.


person Paolo Tedesco    schedule 09.10.2008    source источник


Ответы (6)


У вас есть два достойных варианта:

  1. Стандартный формат файла конфигурации Python с использованием ConfigParser
  2. YAML с использованием такой библиотеки, как PyYAML

Стандартные файлы конфигурации Python выглядят как файлы INI с парами [sections] и key : value или key = value. Преимущества этого формата:

  • Нет необходимости в сторонних библиотеках
  • Простой, знакомый формат файла.

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

file .* does not exist : file not found
user .* not found : authorization error

Или вот так:

{ file .* does not exist: file not found,
  user .* not found: authorization error }

Использование PyYAML не может быть проще:

import yaml

errors = yaml.load(open('my.yaml'))

На данный момент errors — это словарь Python с ожидаемым форматом. YAML может представлять не только словари: если вы предпочитаете список пар, используйте этот формат:

-
  - file .* does not exist 
  - file not found
-
  - user .* not found
  - authorization error

Or

[ [file .* does not exist, file not found],
  [user .* not found, authorization error]]

Что создаст список списков при вызове yaml.load.

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

Для ознакомления с форматом YAML потребуется немного больше времени, но использование PyYAML даже проще, чем использование ConfigParser, с тем преимуществом, что у вас больше возможностей для представления ваших данных с помощью YAML.

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

Удачи!

person Aaron Hays    schedule 09.10.2008
comment
Что не так с JSON в качестве нотации для файлов конфигурации? - person S.Lott; 10.10.2008
comment
JSON тоже должен работать, я просто лучше знаком с YAML. Конечно, в 2.6 есть новый модуль json, что удобно. - person Aaron Hays; 10.10.2008
comment
JSON лучше, чем XML, но волнистые скобки и требование заключать все строки в кавычки (включая ключи) делают его менее удобным для человека. - person mattdm; 13.03.2012
comment
На самом деле не так уж и хорошо, что python требует внешней зависимости для поддержки YAML. - person ; 08.09.2012
comment
@S.Lott, если вы используете JSON для своих файлов конфигурации, получайте удовольствие, не имея возможности ничего комментировать! - person Maxy-B; 18.10.2012

Иногда я просто пишу модуль Python (то есть файл) с именем config.py или что-то со следующим содержимым:

config = {
    'name': 'hello',
    'see?': 'world'
}

затем это можно «прочитать» так:

from config import config
config['name']
config['see?']

легкий.

person Daren Thomas    schedule 09.10.2008
comment
Хорошо, но словарь слов в вопросе несколько вводит в заблуждение. Регулярное выражение не может работать как ключ, ему нужен список пар... - person Federico A. Ramponi; 09.10.2008
comment
@Federico: шаблон регулярного выражения может быть ключом: Patterns = { 'файл .* не существует': 'файл не найден', 'пользователь .* не найден': 'ошибка авторизации', } - person davidavr; 09.10.2008
comment
Хорошо, давраамиды, но как вы собираетесь его использовать? Я бы предпочел что-то вроде: for (regexp,m) в сообщениях: if regexp.match(string): print m - person Federico A. Ramponi; 09.10.2008
comment
@Federico: очень похоже на ваш, например: для шаблона, msg в config.patterns: если re.search(шаблон, строка): напечатать msg - person davidavr; 09.10.2008

Я слышал, что с ConfigObj работать проще чем КонфигПарсер. Он используется многими крупными проектами, IPython, Trac, Turbogears и т. д.

Из их введения:

ConfigObj — это простая, но мощная программа для чтения и записи конфигурационных файлов: круговой обход INI-файлов. Его главная особенность заключается в том, что он очень прост в использовании, с простым программным интерфейсом и простым синтаксисом для конфигурационных файлов. Зато у него много других функций:

  • Вложенные разделы (подразделы), на любой уровень
  • Список значений
  • Несколько строковых значений
  • Интерполяция строк (подстановка)
  • Integrated with a powerful validation system
    • including automatic type checking/conversion
    • повторяющиеся разделы
    • и разрешить значения по умолчанию
  • При записи файлов конфигурации ConfigObj сохраняет все комментарии и порядок элементов и разделов.
  • Множество полезных методов и опций для работы с конфигурационными файлами (например, метод перезагрузки)
  • Полная поддержка Юникода
person sheats    schedule 09.10.2008
comment
Преимущество по сравнению с собственным ConfigParser Python заключается в том, что разделы не требуются. - person djeikyb; 04.02.2012

Я думаю, вам нужен модуль ConfigParser в стандартной библиотеке. Он читает и записывает файлы стиля INI. Примеры и документация в стандартной документации, на которую я ссылался, очень исчерпывающие.

person Andrew Wilkinson    schedule 09.10.2008

Если вы единственный, кто имеет доступ к файлу конфигурации, вы можете использовать простое низкоуровневое решение. Сохраните «словарь» в текстовом файле в виде списка кортежей (regexp, message) точно так же, как если бы это было выражение Python:

[
("file .* does not exist", "file not found"),
("user .* not authorized", "authorization error")
]
В вашем коде загрузите его, затем оцените его и скомпилируйте регулярные выражения в результате:
f = open("messages.py")
messages = eval(f.read()) # caution: you must be sure of what's in that file
f.close()
messages = [(re.compile(r), m) for (r,m) in messages]
и вы получите список кортежей (compiled_regexp, message).

person Federico A. Ramponi    schedule 09.10.2008
comment
Это прекрасно работает. Синтаксис прост в написании и проверке. Что, если кто-то поместит опасный код в файл конфигурации? вопрос сумасшедший. Если есть сомнения, ПОГОВОРИТЕ с людьми, имеющими доступ к конфигу. - person S.Lott; 09.10.2008
comment
Зачем возиться с eval? Просто сделайте свой конфигурационный файл скриптом Python и импортируйте его. - person davidavr; 09.10.2008
comment
Да, да, после прочтения ветки, теперь я думаю, что буду придерживаться решения сценария импорта... - person Federico A. Ramponi; 09.10.2008

Обычно я делаю так, как предложил Дарен, просто сделайте ваш конфигурационный файл скриптом Python:

patterns = {
    'file .* does not exist': 'file not found',
    'user .* not found': 'authorization error',
}

Затем вы можете использовать его как:

import config

for pattern in config.patterns:
    if re.search(pattern, log_message):
        print config.patterns[pattern]

Кстати, это то, что Django делает со своим файлом настроек.

person davidavr    schedule 09.10.2008