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