2013-06-17 5 views
2

Я пытаюсь преобразовать:Как конвертировать Unicode ДИКТ в Сыроватского

datalist = [u"{gallery: 'gal1', smallimage: 'http://www.styleever.com/media/catalog/product/cache/1/small_image/445x370/17f82f742ffe127f42dca9de82fb58b1/2/_/2_12.jpg',largeimage: 'http://www.styleever.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/2/_/2_12.jpg'}", 
u"{gallery: 'gal1', smallimage: 'http://www.styleever.com/media/catalog/product/cache/1/small_image/445x370/17f82f742ffe127f42dca9de82fb58b1/3/_/3_13.jpg',largeimage: 'http://www.styleever.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/3/_/3_13.jpg'}", 
u"{gallery: 'gal1', smallimage: 'http://www.styleever.com/media/catalog/product/cache/1/small_image/445x370/17f82f742ffe127f42dca9de82fb58b1/5/_/5_3_1.jpg',largeimage: 'http://www.styleever.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/5/_/5_3_1.jpg'}", 
u"{gallery: 'gal1', smallimage: 'http://www.styleever.com/media/catalog/product/cache/1/small_image/445x370/17f82f742ffe127f42dca9de82fb58b1/1/_/1_22.jpg',largeimage: 'http://www.styleever.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/1/_/1_22.jpg'}", 
u"{gallery: 'gal1', smallimage: 'http://www.styleever.com/media/catalog/product/cache/1/small_image/445x370/17f82f742ffe127f42dca9de82fb58b1/4/_/4_7_1.jpg',largeimage: 'http://www.styleever.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/4/_/4_7_1.jpg'}"] 

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

for i in datalist: 
    print i['smallimage'] 
    ....:  

--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-20-686ea4feba66> in <module>() 
     1 for i in datalist: 
----> 2  print i['smallimage'] 
     3 

TypeError: string indices must be integers 

Как преобразовать список, содержащий Unicode Dict в Словаре ..

ответ

8

Вы можете использовать demjson модуль, который имеет нестрогое режим, который обрабатывает данные, которые вы имеете:

import demjson 

for data in datalist: 
    dct = demjson.decode(data) 
    print dct['gallery'] # etc... 
+3

Хорошая находка. Джон. Мне это нравится. (+1) – mgilson

+0

Я все еще не вижу необходимости в этом ... Зачем импортировать что угодно, когда вы можете просто «[dict ((str (ключ), значение) для (key, value) в adict.items ()] ' – bnlucas

+2

@bnlucas, потому что на этом этапе нет словарей? –

2

Если ключи словаря были процитированы, вы могли бы использовать json.loads для загрузки Струна.

import json 
for i in datalist: 
    print json.loads(i)['smallimage'] 

(ast.literal_eval работал бы тоже ...)

однако, как она есть, это будет работать со старой школой eval:

>>> class Mdict(dict): 
...  def __missing__(self,key): 
...  return key 
... 
>>> eval(datalist[0],Mdict(__builtins__=None)) 
{'largeimage': 'http://www.styleever.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/2/_/2_12.jpg', 'gallery': 'gal1', 'smallimage': 'http://www.styleever.com/media/catalog/product/cache/1/small_image/445x370/17f82f742ffe127f42dca9de82fb58b1/2/_/2_12.jpg'} 

Следует отметить, что это, вероятно, уязвимы для инъекций, поэтому используйте его только в том случае, если строка принадлежит доверенному источнику.


Наконец, для тех, кто хочет короткий, хотя и несколько плотное решение, которое использует только стандартную библиотеку и не уязвимы для инъекций атак ... Этот маленький драгоценный камень делает трюк (в предположении, что ключи словаря действительны идентификаторы)!

import ast 
class RewriteName(ast.NodeTransformer): 
    def visit_Name(self,node): 
     return ast.Str(s=node.id) 

transformer = RewriteName() 
for x in datalist: 
    tree = ast.parse(x,mode='eval') 
    transformer.visit(tree) 
    print ast.literal_eval(tree)['smallimage'] 
+0

@MartijnPieters - Вы правы (облом). Я полагаю, что самый простой (хотя и не самый безопасный) подход - использовать регулярный 'eval' ... :-( – mgilson

+0

Приятный трюк с преобразованием имен в строки, это будет работать, пока ключи также являются действительными идентификаторами Python. –

+0

@MartijnPieters - Правильно. Не думал об этом оговорке. Я полагаю, что это также присутствует в моем первоначальном ответе ... – mgilson

3

В этом случае, я бы вручную обработать регулярное выражение, чтобы сделать это в то, что вы можете оценить, как Python:

import re 
import ast 
from functools import partial 

keys = re.compile(r'(gallery|smallimage|largeimage)') 
fix_keys = partial(keys.sub, r'"\1"') 

for entry in datalist: 
    entry = ast.literal_eval(fix_keys(entry)) 

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

Результат:

>>> for entry in datalist: 
...  print ast.literal_eval(fix_keys(entry)) 
... 
{'largeimage': 'http://www.styleever.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/2/_/2_12.jpg', 'gallery': 'gal1', 'smallimage': 'http://www.styleever.com/media/catalog/product/cache/1/small_image/445x370/17f82f742ffe127f42dca9de82fb58b1/2/_/2_12.jpg'} 
{'largeimage': 'http://www.styleever.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/3/_/3_13.jpg', 'gallery': 'gal1', 'smallimage': 'http://www.styleever.com/media/catalog/product/cache/1/small_image/445x370/17f82f742ffe127f42dca9de82fb58b1/3/_/3_13.jpg'} 
{'largeimage': 'http://www.styleever.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/5/_/5_3_1.jpg', 'gallery': 'gal1', 'smallimage': 'http://www.styleever.com/media/catalog/product/cache/1/small_image/445x370/17f82f742ffe127f42dca9de82fb58b1/5/_/5_3_1.jpg'} 
{'largeimage': 'http://www.styleever.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/1/_/1_22.jpg', 'gallery': 'gal1', 'smallimage': 'http://www.styleever.com/media/catalog/product/cache/1/small_image/445x370/17f82f742ffe127f42dca9de82fb58b1/1/_/1_22.jpg'} 
{'largeimage': 'http://www.styleever.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/4/_/4_7_1.jpg', 'gallery': 'gal1', 'smallimage': 'http://www.styleever.com/media/catalog/product/cache/1/small_image/445x370/17f82f742ffe127f42dca9de82fb58b1/4/_/4_7_1.jpg'} 
+0

@Downvoter вы любезно объясняете причину downvoting – jamylak

+0

(я не уменьшил это значение), но это не удастся, если значения в dict содержат любую из этих строк. Он также потерпит неудачу, если есть другие ключи, которые не были мужчинами в явном виде. – mgilson

+0

Не уменьшилось. Я бы использовал регулярное выражение, подобное этому: '(?: {|,) ([^:] +)' – enpenax

0

Ваш DataList является list из Юникода строк.

Вы можете использовать eval, за исключением того, что ваши ключи неправильно указаны. что вы можете сделать, это реквот ключи на лету с replace:

for i in datalist: 
    my_dict = eval(i.replace("gallery", "'gallery'").replace("smallimage", "'smallimage'").replace("largeimage", "'largeimage'")) 
    print my_dict["smallimage"] 
+2

использовать' ast.literal_eval' над 'eval' всякий раз, когда вы можете – jamylak

+0

нормально, спасибо за отзыв, Я не знал об аске.literal_eval – njzk2

-4

Я не понимаю, почему необходимость для всех дополнительных вещей, таких как использование re или json ...

fdict = {str(k): v for (k, v) in udict.items()} 

Где udict является dict с ключами unicode. Просто преобразуйте их в str. В ваших данных вы можете просто ...

datalist = [dict((str(k), v) for (k, v) in i.items()) for i in datalist] 

Простой тест:

>>> datalist = [{u'a':1,u'b':2},{u'a':1,u'b':2}] 
[{u'a': 1, u'b': 2}, {u'a': 1, u'b': 2}] 
>>> datalist = [dict((str(k), v) for (k, v) in i.items()) for i in datalist] 
>>> datalist 
[{'a': 1, 'b': 2}, {'a': 1, 'b': 2}] 

Нет import re или import json. Просто и быстро.

+1

Вы прочитали вопрос или посмотрели образцы данных? – mgilson

+0

Это не работает для данных образца, ** вообще **: 'Объект AttributeError: 'unicode' не имеет атрибутов 'items''. Вход представляет собой список строк юникода, ** не ** список словарей. –

+0

Я ушел с вопроса, поэтому извиняюсь за то, что не подгонял данные примера. Теперь я вижу, как каждый элемент является строкой. Мой ответ ** будет ** конвертировать 'unicode'' dict' в обычный 'dict'. – bnlucas

3

Как и в другой мысли, ваш список правильно отформатирован Yaml.

> yaml.load(u'{foo: "bar"}')['foo'] 
'bar' 

И если вы хотите быть действительно фантазии и разобрать все сразу:

> data = yaml.load('['+','.join(datalist)+']') 
> data[0]['smallimage'] 
'http://www.styleever.com/media/catalog/product/cache/1/small_image/445x370/17f82f742ffe127f42dca9de82fb58b1/2/_/2_12.jpg' 
> data[3]['gallery'] 
'gal1' 
Смежные вопросы