Skip to main content
 首页 » 编程设计

python之为什么 pyparser 的 asDict() 返回一个空的字典而不是一个列表

2025年05月04日29zhwl

我正在尝试编写解析器来处理来自注册商 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': {}}} 

errors['username'] 应该是一个字符串列表,但显示为空字典。当我 .dump() 参数时,看起来一切正常:

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 

我在这里做错了什么?

请您参考如下方法:

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

编辑

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

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

由于这将返回解析列表而不是 ParseResults,而是作为实际列表,toDict() 不会尝试将其转换为字典。