Разбор файла данных в python (2.5.2) - PullRequest
1 голос
/ 17 декабря 2009

У меня есть файл определения сообщения, который выглядит так

struct1 
{
  field="name" type="string" ignore="false"; 
  field="id" type="int" enums=" 0="val1" 1="val2" ";
}

struct2
{
  field = "object" type="struct1";
  ...
}

Как я могу разобрать это в словарь с ключами 'struct1, struct2', и значения должны быть списком словарей, каждому из которых соответствует соответствующий номер строки, чтобы я мог сделать следующее

dict['struct1'][0]['type'] // Would return 'string'
dict['struct1'][1]['type'] // Would return 'int'
dict['struct1'][1]['enums']['0'] // Would return 'val1'
dict['struct2'][0]['type'] // Would return 'struct1'

и т. Д. *

Кроме того, я могу изменить формат файла определения, и если у кого-либо из вас есть предложения по изменению формата файла определения, чтобы облегчить анализ, пожалуйста, дайте мне знать.

Спасибо

Ответы [ 6 ]

4 голосов
/ 17 декабря 2009

Могу ли я порекомендовать YAML ? ИМХО синтаксис более читабелен для ввода данных, и тогда вам не нужно писать и поддерживать парсер. Eschew XML - это хорошо для разметки текста, но не хорошо для ввода данных, так как текст не читается человеком со всеми дублирующими тегами везде.

4 голосов
/ 17 декабря 2009

Используйте взамен YAML . Для Python есть библиотека PyYAML . Он активно используется Google AppEngine.

Это просто дружеское предложение: -)

Пример (отображение скаляров на последовательности):

american:
  - Boston Red Sox
  - Detroit Tigers
  - New York Yankees
national:
  - New York Mets
  - Chicago Cubs
  - Atlanta Braves

Существует также JSON, который, конечно, имеет достаточную поддержку Python (но, как правило, больше травмирует пальцы; -)

4 голосов
/ 17 декабря 2009

Использование может использовать json в качестве формата файла, он поддерживает (в языке Python) словари и списки. Поскольку поддержка json встроена только для python 2.6 и выше, вам понадобится эта библиотека: http://pypi.python.org/pypi/simplejson/2.0.9

{ "struct1" 
    [
        {"field" : "name", "type" : "string", "ignore" : false },
        {"field" : "id", "type" : "int", "0" : "val1", "1" : "val2" }
        {"field" : "id", "type" : "int", "enums" : { "0": "val1", "1": "val2"}}
    ]
  "struct2"
    [ ... ]
}

часть питона (набросок, не проверен):

>>> import simplejson as json
>>> d = json.loads(yourjsonstring)
>>> d['struct1'][0]['field']
name
>>> d['struct1'][2]['enums']['0']
val1
...
2 голосов
/ 17 декабря 2009

Я бы просто использовал Python для формата файла определения сообщения.

Пусть ваш файл определения сообщения представляет собой обычный файл Python:

# file messages.py
messages = dict(
    struct1=[
        dict(field="name", type="string", ignore=False),
        dict(field="id", type="int", enums={0: "val1", 1: "val2"}),
        ],
    struct2=[
        dict(field="object", type="struct1"),
        ]
    )

Ваша программа может импортировать и использовать эту структуру данных напрямую:

# in your program
from messages import messages
print messages['struct1'][0]["type"]
print messages['struct1'][1]['type']
print messages['struct1'][1]['enums'][0]
print messages['struct2'][0]['type']

Используя этот подход, вы позволяете Python выполнять анализ за вас.

И вы также получаете много возможностей. Например, представьте, что у вас (по какой-то странной причине) есть структура сообщения с 1000 полями с именем «field_N». Используя обычный формат файла, вам нужно будет добавить 1000 строк определений полей (если вы не создадите какой-то цикл в вашем анализаторе конфигурационных файлов - вы все равно будете на пути к созданию языка программирования). Используя для этого Python, вы можете сделать что-то вроде:

messages = dict(
    ...
    strange_msg=[dict(field="field_%d" % i) for i in range(1000)],
    ...
    )

Кстати, в Python 2.6 использование именованных кортежей вместо dict является опцией. Или используйте один из многочисленных доступных классов «Связка» (см. Кулинарную книгу Python для именованного кортежа для 2.5).

EDIT:

Ниже приведен код, который читает файлы определения сообщений, как указано в командной строке. Он использует execfile вместо import.

# file mainprogram.py

def read_messages_from_file(filename):
    module_dict = {}
    execfile(filename, module_dict)
    return module_dict['messages']

if __name__ == "__main__":
    from pprint import pprint
    import sys

    for arg in sys.argv[1:]:
        messages = read_messages_from_file(arg)
        pprint(messages)

Выполнение:

$ python mainprogram.py messages1 messages2 messages3

будет читать и распечатывать сообщения, определенные в каждом файле.

1 голос
/ 17 декабря 2009

Pyparsing - это хорошая простая в использовании библиотека. Вот что бы я использовал.

http://pyparsing.wikispaces.com/

0 голосов
/ 17 декабря 2009

Поскольку вы можете изменять формат файла, вы можете изменить его на любой из нескольких форматов, в которых есть библиотеки Python для чтения и записи. Например, JSON, YAML, XML или даже встроенный ConfigParser .

[struct1]
field: name
type: string
ignore: false
# etc.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...