Файл конфигурации со списком пар ключ-значение в python
У меня есть python script, который анализирует набор сообщений об ошибках и проверяет каждое сообщение, если оно соответствует определенному шаблону (регулярному выражению), чтобы сгруппировать эти сообщения. Например, "файл x не существует" и "файл y не существует" будет соответствовать "file. * Не существует" и учитывается как два вхождения категории "файл не найден".
По мере роста числа шаблонов и категорий я хотел бы поместить эти пары "регулярное выражение/отображаемая строка" в файл конфигурации, в основном, сериализацию словаря.
Я хотел бы, чтобы этот файл редактировался вручную, поэтому я отказываюсь от любой формы двоичной сериализации, а также я бы предпочел не прибегать к сериализации xml, чтобы избежать проблем с символами для выхода (& < > и так далее...).
Есть ли у вас какое-либо представление о том, что может быть хорошим способом достижения этого?
Обновление: спасибо Дарен Томас и Федерико Рампони, но я не могу иметь внешний файл python с возможным произвольным кодом.
Ответы
Ответ 1
У вас есть два достойных варианта:
- Стандартный формат файла конфигурации Python
используя ConfigParser
- 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
или
[ [file .* does not exist, file not found],
[user .* not found, authorization error]]
Будет создан список списков при вызове yaml.load
.
Одно из преимуществ YAML заключается в том, что вы можете использовать его для экспорта существующих, жестко кодированных данных в файл для создания исходной версии, вместо того, чтобы вырезать/вставить плюс кучу find/replace, чтобы получить данные в правый формат.
Формат YAML займет немного больше времени, чтобы ознакомиться с ним, но использование PyYAML еще проще, чем использование ConfigParser с тем преимуществом, что у вас есть больше возможностей для представления ваших данных с помощью YAML.
Любой из них, похоже, будет соответствовать вашим текущим потребностям, ConfigParser будет легче начать, в то время как YAML дает вам больше гибкости в будущем, если ваши потребности будут расширяться.
Удачи!
Ответ 2
Я иногда просто пишу модуль python (т.е. файл) под названием config.py
или что-то со следующим содержимым:
config = {
'name': 'hello',
'see?': 'world'
}
тогда это может быть "прочитано" следующим образом:
from config import config
config['name']
config['see?']
легко.
Ответ 3
Я слышал, что ConfigObj легче работать, чем ConfigParser. Он используется множеством больших проектов, IPython, Trac, Turbogears и т.д.
Из introduction:
ConfigObj - это простой, но мощный файловый ридер и сценарист: файловый круглый триппер. Его основная особенность заключается в том, что он очень прост в использовании, с простым интерфейсом программиста и простым синтаксисом для файлов конфигурации. У этого есть много других особенностей, хотя:
- Вложенные разделы (подразделы) на любой уровень
- Значения списков
- Несколько значений строк
- Строковая интерполяция (подстановка)
- Интегрировано с мощной системой проверки
- включая автоматическую проверку/преобразование типов
- повторные разделы
- и значения по умолчанию
- При записи конфигурационных файлов ConfigObj сохраняет все комментарии и порядок членов и разделов
- Много полезных методов и возможностей для работы с файлами конфигурации (например, метод reload)
- Поддержка полного Unicode
Ответ 4
Я думаю, что вы хотите ConfigParser модуль в стандартной библиотеке. Он читает и записывает файлы стиля INI. Примеры и документация в стандартной документации, к которой я привязан, очень полны.
Ответ 5
Если вы единственный, у кого есть доступ к файлу конфигурации, вы можете использовать простое, низкоуровневое решение. Держите "словарь" в текстовом файле как список кортежей (regexp, message) точно так же, как если бы это было выражение python:
[
("file .* does not exist", "file not found"),
("user .* not authorized", "authorization error")
]
In your code, load it, then eval it, and compile the regexps in the result:
f = open("messages.py")
messages = eval(f.read()) # caution: you must be sure of what in that file
f.close()
messages = [(re.compile(r), m) for (r,m) in messages]
and you end up with a list of tuples (compiled_regexp, message).
Ответ 6
Я обычно делаю, как предложил Дарен, просто сделайте свой конфигурационный файл Python script:
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 делает со своим файлом настроек, кстати.