Python: чтение файла конфигурации с несколькими строками на ключ
Я пишу небольшой тестовый пакет DB, который читает файлы конфигурации с запросами и ожидаемыми результатами, например:
query = "SELECT * from cities WHERE name='Unknown';"
count = 0
level = 1
name = "Check for cities whose name should be null"
suggested_fix = "UPDATE cities SET name=NULL WHERE name='Unknown';"
Это хорошо работает; Я разделяю каждую строку, используя Python string.partition('=')
.
Моя проблема - очень длинные SQL-запросы. В настоящее время я просто вставляю эти запросы в один лайнер, который является уродливым и неподъемным.
Я хочу найти элегантный, Pythonic способ читать право выражения, даже если он охватывает много строк.
Примечания:
- мои SQL-запросы могут содержать
=
- Мне не нравится идея форсировать
"
вокруг правой стороны, потому что там есть много существующих файлов.
EDIT:
ConfigParser отлично, но он заставляет меня добавить пробел или вкладку в начале каждой строки в многострочной записи. Это может быть большой болью.
Спасибо заранее,
Адам
Ответы
Ответ 1
Это почти точно прецедент, который заставил нас переключиться на YAML (Wikipedia, реализация python, documentation, вы можете посмотреть JSON в качестве альтернативы). YAML имеет некоторые преимущества перед configparser
или json
- удобочитаемость человека (лучше, чем JSON для больших файлов);
- может сериализовать произвольные объекты python (что делает его небезопасным как
pickle
, но в реализации python есть функция safe_load
, чтобы облегчить эту проблему). Это уже полезно для чего-то простого, как объект datetime
.
В целях полноты основные недостатки (IMO):
- реализация Python на порядок медленнее реализации JSON;
- менее переносимый на разных платформах, чем JSON.
Например
import yaml
sql = """
query : "SELECT * from cities
WHERE name='Unknown';"
count : 0
level : 1
name : "Check for cities whose name should be null"
suggested_fix : "UPDATE cities SET name=NULL WHERE name='Unknown';"
"""
sql_dict = yaml.safe_load(sql)
print(sql_dict['query'])
печатает
SELECT * from cities WHERE name='Unknown';
Ответ 2
Стандартная библиотека библиотеки Python ConfigParser поддерживает это по умолчанию. Файл конфигурации должен быть в стандартном формате:
[Long Section]
short: this is a normal line
long: this value continues
in the next line
Файл конфигурации выше можно прочитать с помощью следующего кода:
import ConfigParser
config = ConfigParser.ConfigParser()
config.read('longsections.cfg')
long = config.get('Long Section', 'long')
Ответ 3
Я бы предложил использовать регулярное выражение... Код может выглядеть так, чтобы вы начали:
import re
test="""query = "select * from cities;"
count = 0
multine_query = "select *
from cities
where name='unknown';"
"""
re_config = re.compile(r'^(\w+)\s*=\s*((?:".[^"]*")|(?:\d+))$', re.M)
for key, value in re_config.findall(test):
if value.startswith('"'):
value = value[1:-1]
else:
value = int(value)
print key, '=', repr(value)
Результат этого примера:
~> python test.py
query = 'select * from cities;'
count = 0
multine_query = "select *\nfrom cities\n where name='unknown';"
Надеюсь, что это поможет!
С уважением,
Christoph