Подтвердить что ты не робот

Как я могу сериализовать словарь Python в строку, а затем вернуться к словарю?

Как сериализовать словарь Python в строку, а затем вернуться к словарю? Словарь будет иметь списки и другие словари внутри него.

4b9b3361

Ответ 1

Это зависит от того, для чего вы хотите его использовать. Если вы просто пытаетесь его сохранить, вы должны использовать pickle (или, если вы используете CPython 2.x, cPickle, что быстрее).

>>> import pickle
>>> pickle.dumps({'foo': 'bar'})
b'\x80\x03}q\x00X\x03\x00\x00\x00fooq\x01X\x03\x00\x00\x00barq\x02s.'
>>> pickle.loads(_)
{'foo': 'bar'}

Если вы хотите, чтобы он был доступен для чтения, вы можете использовать json:

>>> import json
>>> json.dumps({'foo': 'bar'})
'{"foo": "bar"}'
>>> json.loads(_)
{'foo': 'bar'}

json, однако, очень ограничен в том, что он будет поддерживать, в то время как pickle может использоваться для произвольных объектов (если он не работает автоматически, класс может определить __getstate__ чтобы точно указать, как его следует мариновать).

>>> pickle.dumps(object())
b'\x80\x03cbuiltins\nobject\nq\x00)\x81q\x01.'
>>> json.dumps(object())
Traceback (most recent call last):
  ...
TypeError: <object object at 0x7fa0348230c0> is not JSON serializable

Ответ 2

Используйте Python json модуль, или simplejson если у вас нет python 2.6 или выше.

Ответ 3

Если вы полностью доверяете строке и не заботитесь о атаках инъекции python, то это очень простое решение:

d = { 'method' : "eval", 'safe' : False, 'guarantees' : None }
s = str(d)
d2 = eval(s)
for k in d2:
    print k+"="+d2[k]

Если вы более безопасны, то ast.literal_eval - лучшая ставка.

Ответ 4

Pickle отлично, но я думаю, что стоит упомянуть literal_eval из модуля ast для еще более легкого весового решения, если вы только сериализуете базовые типы python. Это в основном "безопасная" версия пресловутой функции eval, которая позволяет оценивать базовые типы python, а не любой действительный код python.

Пример:

>>> d = {}
>>> d[0] = range(10)
>>> d['1'] = {}
>>> d['1'][0] = range(10)
>>> d['1'][1] = 'hello'
>>> data_string = str(d)
>>> print data_string
{0: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], '1': {0: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 1: 'hello'}}

>>> from ast import literal_eval
>>> d == literal_eval(data_string)
True

Одно из преимуществ заключается в том, что сериализованные данные - это всего лишь код python, поэтому он очень дружелюбен к человеку. Сравните это с тем, что вы получили бы с помощью pickle.dumps:

>>> import pickle
>>> print pickle.dumps(d)
(dp0
I0
(lp1
I0
aI1
aI2
aI3
aI4
aI5
aI6
aI7
aI8
aI9
asS'1'
p2
(dp3
I0
(lp4
I0
aI1
aI2
aI3
aI4
aI5
aI6
aI7
aI8
aI9
asI1
S'hello'
p5
ss.

Недостатком является то, что, как только данные включают тип, который не поддерживается literal_ast, вам придется перейти к чему-то еще, как травление.

Ответ 5

Одна вещь json не может сделать, это dict с индексом с цифрами. Следующий фрагмент

import json
dictionary = dict({0:0, 1:5, 2:10})
serialized = json.dumps(dictionary)
unpacked   = json.loads(serialized)
print unpacked[0]

будет бросать

KeyError: 0

Поскольку ключи преобразуются в строки. cPickle сохраняет числовой тип, и распакованный dict может быть использован сразу.

Ответ 6

Хотя не строго сериализация, json может быть разумным подходом здесь. Это будет обрабатывать вложенные dicts и списки и данные, пока ваши данные "просты": строки и базовые числовые типы.

Ответ 7

pyyaml ​​ также следует упомянуть здесь. Он является читаемым человеком и может сериализовать любой объект python.
Здесь находится pyyaml:
 https://bitbucket.org/xi/pyyaml

Ответ 8

Если вы пытаетесь только сериализовать, то pprint также может быть хорошим вариантом. Он требует, чтобы объект был сериализован и потоком файлов.

Вот код:

from pprint import pprint
my_dict = {1:'a',2:'b'}
with open('test_results.txt','wb') as f:
    pprint(my_dict,f)

Я не уверен, можно ли легко десериализовать. Я использовал json для сериализации и deserialze раньше, который работает правильно в большинстве случаев.

f.write(json.dumps(my_dict, sort_keys = True, indent = 2, ensure_ascii=True))

Однако в одном конкретном случае были ошибки, записывающие данные не-unicode в json.