2015-03-05 3 views
1

Я новичок в Python и пытаюсь найти самый Pythonic способ разобрать ответ из запроса LDAP. Пока что у меня есть работы, но я хотел бы сделать его более аккуратным, если это возможно. Мои данные ответа заключается в следующем:Каков наилучший Pythonic способ разобрать эти данные?

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

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

"department:theDepartment,mail:[email protected]" 

Я «Сейчас я чувствую (и выглядит) действительно грубой силой, но работает. Я добавил дополнительные комментарии и результаты вывода на основе того, что каждый шаг делает, чтобы попытаться разработать этот беспорядок.

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

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

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

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

#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:[email protected]"] 

Хотя я большой поклонник «если он не сломался, не исправляйте его» Я больше поклонник эффективности.

EDIT Это в конечном итоге работает для меня в принятом ответе ниже по @Mario

myUser = ast.literal_eval(str(result_set[0]))[0][1] 
myUserDict = { k: v[0] for k, v in myUser.iteritems() } 
+1

Похоже на то, что может сделать анализатор JSON. Кроме того, поскольку вас интересует только то, что находится между фигурными фигурными скобками, вы можете создать простое регулярное выражение для его синтаксического анализа. –

+0

Рассмотрите отчетный ответ [на этот вопрос] (http://stackoverflow.com/questions/13297654/convert-string-into-dictionary-with-python). Кажется, что это работает для 'x = '{' department ': [' theDepartment '],' mail ': [' [email protected] ']}" ' – jedwards

+0

Если весь вывод был действительным, это будет легко. ;) – Dan

ответ

4

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

import ast 

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

# 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.


Edit: Другой пользователь в этом потоке предлагает использовать функцию 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

+2

Рассмотрите возможность использования ast.literal_eval над eval –

+1

Я включил ваше предложение, но в другом месте этой темы OP упоминает, что он получает входные данные из модуля python-ldap. Модуль обрабатывает исходный ввод, поэтому я собираюсь догадаться, что он уже проверен. (Я не видел его упоминания об этом, пока не отредактировал свой ответ.) Я не знал об альтернативе eval, поэтому спасибо вам за это. – Mario

+1

Я закончил тем, что начал работать. Я все еще разбираюсь в том, как работает AST для справки, но это было похоже на магию. Спасибо за помощь! 'myUser = ast.literal_eval (str (result_set [0])) [0] [1] myUserDict = {k: v [0] для k, v в myUser.iteritems()}' – Dan

2

Учитывая это использует ast.literal_eval он не идеален, но он уверен, уборщик

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

По какой-либо причине это всегда будет возвращать ** N **. – Dan

Смежные вопросы