Python: чтение файла конфигурации с несколькими строками на ключ - PullRequest
11 голосов
/ 11 февраля 2010

Я пишу небольшой набор тестов БД, который читает конфигурационные файлы с запросами и ожидаемыми результатами, например ::10000

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';"

Это хорошо работает; Я делю каждую строку, используя string.partition('=').

Python

Моя проблема - очень длинные запросы SQL. В настоящее время я просто вставляю эти запросы как однострочный, что некрасиво и не поддерживается.

Я хочу найти элегантный, Pythonic способ прочитать право выражения, даже если он занимает много строк.

Примечания:

  • мои запросы SQL могут содержать =
  • Мне не нравится идея навязывать " с правой стороны, потому что есть много существующих файлов без него.

EDIT:

ConfigParser отлично, но это заставляет меня добавлять пробел или табуляцию в начале каждой строки многострочной записи. Это может быть большой болью.

Заранее спасибо,

Адам

Ответы [ 3 ]

16 голосов
/ 11 февраля 2010

Модуль стандартной библиотеки 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')
10 голосов
/ 12 февраля 2010

Это почти точно сценарий использования, который заставил нас перейти на YAML ( Википедия , реализация Python , документация ; вы Возможно, вы захотите посмотреть на JSON в качестве альтернативы). YAML имеет некоторые преимущества перед configparser или json:

  • удобочитаемость для человека (лучше, чем JSON для больших файлов);
  • может сериализовать произвольные объекты Python (что делает его таким же небезопасным, как pickle, но в реализации Python есть функция safe_load для решения этой проблемы). Это уже полезно для чего-то такого простого, как datetime объект.

Для полноты картины основные недостатки (ИМО):

  • Реализация 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';
1 голос
/ 11 февраля 2010

Я бы предложил использовать регулярное выражение ... Код может выглядеть следующим образом:

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

...