为什么pyparser的asDict()返回一个空的dict而不是一个列表?

时间:2016-03-06 02:12:25

标签: python parsing pyparsing

我正在尝试编写解析器来处理来自注册商API的响应数据。格式不是我之前见过的格式,所以这可能很容易;如果有人认出它,请告诉我,可能有一个预先存在的库来处理它。但是现在我的运作假设我自己需要解析它。

我的语法看起来像这样:

equals = Literal("=").suppress()
lbracket = Literal("[").suppress()
rbracket = Literal("]").suppress()
lbrace = Literal("{").suppress()
rbrace = Literal("}").suppress()

value_dict          = Forward()
value_list          = Forward()
value_string        = Word(alphanums + "@. ")

value               = value_list ^ value_dict ^ value_string
values              = Group(delimitedList(value, ","))
value_list          << lbracket + values + rbracket

identifier          = Word(alphanums + "_.")

assignment          = Group(identifier + equals + Optional(value))
assignments         = Dict(delimitedList(assignment, ';'))
value_dict          << lbrace + assignments + rbrace

response = assignments

当我运行这个简单的测试用例时:

rsp = 'username=goat; errors={username=[already taken, too short]}; empty_field='
result = response.parseString(rsp)
print result.asDict()

我得到以下内容:

{'username': 'goat', 'empty_field': '', 'errors': {'username': {}}}

错误[&#39;用户名&#39;]应该是字符串列表,但显示为空字典。当我.dump()params,看起来一切都很好:

ss = response.searchString(rsp)
for i in ss:
    print i.dump()

的产率:

- empty_field: 
- errors: [['username', ['already taken', 'too short']]]
  - username: ['already taken', 'too short']
- username: goat

我在这里做错了什么?

1 个答案:

答案 0 :(得分:0)

在当前版本的pyparsing中,它是asDict()的天真实现。在yoru语法中,您可以创建两种不同样式的ParseResults:具有名称的结果和仅作为普通列表的结果。 asList()只是遍历嵌套的ParseResults获取列表和子列表,因此asDict()的工作方式类似。但是,asDict()确实需要对可能存在的值类型更加智能 - 目前,这是pyparsing中的一个错误。

修改

要解决此问题,您需要做一些工作来将列表存储为实际列表,而不是ParseResults。将values表达式重新定义为:

values = delimitedList(value, ",").setParseAction(lambda toks: [toks.asList()])

因为这会将解析后的列表作为ParseResults返回,但作为实际列表,toDict()将不会尝试将其转换为dict。