解析这些数据的最佳Pythonic方法是什么?

时间:2015-03-05 19:08:33

标签: python python-2.7

我是Python的新手,我正在尝试找到解析LDAP查询响应的最Pythonic方法。到目前为止,我的工作是什么,但如果可能的话,我想让它更整洁。我的回复数据如下:

"[[('CN=LName\\, FName,OU=MinorUserGroup,OU=MajorUserGroup,DC=my,DC=company,DC=com', {'department': ['theDepartment'], 'mail': ['theEmail@mycompany.com']})]]"

在这些数据中,我真的只对{}中的字段感兴趣,以便我可以把它扔进字典......

"department:theDepartment,mail:theEmail@mycompany.com"

我现在所做的事情(而且看起来)真的很蛮力但却有效。我根据每个步骤正在做的事情添加了额外的评论和输出结果,以尝试和详细说明这个混乱。

#Original String
#"[[('CN=LName\\, FName,OU=MinorUserGroup,OU=MajorUserGroup,DC=my,DC=company,DC=com', {'department': ['theDepartment'], 'mail': ['theEmail@mycompany.com']})]]"

#split at open {, take the latter half
myDetails = str(result_set[0]).split('{') 
#myDetails[1] = ["'department': ['theDepartment'], 'mail': ['theEmail@mycompany.com']})]]"]

#split at close }, take the former half
myDetails = str(myDetails[1]).split('}') 
#myDetails[0] = ["'department': ['theDepartment'], 'mail': ['theEmail@mycompany.com']"]

#split at comma to separate the two response fields
myDetails = str(myDetails[0]).split(',') 
#myDetails = ["'department': ['theDepartment']","'mail': ['theEmail@mycompany.com']"]

#clean up the first response field
myDetails[0] = str(myDetails[0]).translate(None, "'").translate(None," [").translate(None,"]") 
#myDetails[0] = ["department:theDepartment"]

#clean up the second response field
myDetails[1] = str(myDetails[1]).translate(None," '").translate(None, "'").translate(None,"[").translate(None,"]")
#myDetails[1] = ["mail:theEmail@mycompany.com"]

虽然我是#34的忠实粉丝,但如果它没有破坏,就不要修复它。"我是效率的忠实粉丝。

修改 根据@Mario

下面接受的答案,这最终为我工作
myUser = ast.literal_eval(str(result_set[0]))[0][1] 
myUserDict = { k: v[0] for k, v in myUser.iteritems() }

2 个答案:

答案 0 :(得分:5)

信任您的输入并指望其严格的规律性,这将解析您的示例数据并生成您期望的内容:

import ast

ldapData = "[[('CN=LName\\, FName,OU=MinorUserGroup,OU=MajorUserGroup,DC=my,DC=company,DC=com', {'department': ['theDepartment'], 'mail': ['theEmail@mycompany.com']})]]"

# Using the ast module's function is much safer than using eval. (See below!)
obj = ast.literal_eval(ldapData)[0][0]
rawDict = obj[1]
data = { k: v[0] for k, v in rawDict.iteritems() }

# The dictionary.
print data

使用大括号的行称为dict comprehension。


编辑:此线程上的另一位用户建议使用ast.literal_eval功能。在研究之后我不得不同意。 eval函数将执行任何字符串。如果输入是这样的,那你就有一个大问题:

eval("__import__('os').system('rm -R *')") 

另一方面,如果使用ast函数解析相同的字符串,则会出现异常:

>>> import ast
>>> ast.literal_eval("__import__('os').system('rm -R *')")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/ast.py", line 80, in literal_eval
    return _convert(node_or_string)
  File "/usr/lib64/python2.7/ast.py", line 79, in _convert
    raise ValueError('malformed string')
ValueError: malformed string
>>> 

进一步的讨论可以在这里找到:

http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html

模块的文档在这里:

https://docs.python.org/2/library/ast.html

答案 1 :(得分:2)

考虑到这使用ast.literal_eval它并不完美,但它确实更清洁

>>> import ast
>>> a = "[[('CN=LName\\, FName,OU=MinorUserGroup,OU=MajorUserGroup,DC=my,DC=company,DC=com', {'department': ['theDepartment'], 'mail': ['theEmail@mycompany.com']})]]"                                                                                                                                                                    
>>> ast.literal_eval(a)[0][0][1]
{'department': ['theDepartment'], 'mail': ['theEmail@mycompany.com']}
>>> type(ast.literal_eval(a)[0][0][1])                                                                                                                               
<type 'dict'>