development

파이썬 사전을 문자열로 직렬화 한 다음 다시 사전으로 어떻게 직렬화합니까?

big-blog 2020. 11. 30. 18:03
반응형

파이썬 사전을 문자열로 직렬화 한 다음 다시 사전으로 어떻게 직렬화합니까?


파이썬 사전을 문자열로 직렬화 한 다음 다시 사전으로 어떻게 직렬화합니까? 사전에는 목록과 기타 사전이 포함됩니다.


사용하려는 용도에 따라 다릅니다. 저장하려는 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

Python의 json 모듈 또는 Python 2.6 이상이 없는 경우 simplejson을 사용합니다.


경우 완전히 문자열을 신뢰하고 걱정하지 않는다 파이썬 주입 공격 다음이 아주 간단한 솔루션입니다 :

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

안전 ast.literal_eval에 더 신경 을 쓰고 있다면 더 나은 방법입니다.


Pickle은 훌륭하지만 기본 파이썬 유형 만 직렬화하는 경우 더 가벼운 솔루션을 위해 모듈 literal_eval에서 언급 할 가치가 있다고 생각합니다 ast. 이것은 기본적으로 eval모든 유효한 파이썬 코드와는 반대로 기본적인 파이썬 유형의 평가만을 허용 하는 악명 높은 함수 의 "안전한"버전입니다 .

예:

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

한 가지 이점은 직렬화 된 데이터가 파이썬 코드 일 뿐이므로 매우 인간 친화적이라는 것입니다. 당신이 얻는 것과 비교하십시오 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산 세척과 같은 다른 유형 으로 전환해야한다는 것입니다.


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것은 즉시 사용할 수 있습니다.


엄격하게 직렬화는 아니지만 json은 여기서 합리적인 접근 방식 일 수 있습니다. 그것은 당신의 데이터가 "단순"한 한, 중첩 된 딕셔너리와리스트, 데이터를 처리 할 것입니다 : 문자열, 기본 숫자 유형.


pyyaml should also be mentioned here. It is both human readable and can serialize any python object.
pyyaml is hosted here:
https://bitbucket.org/xi/pyyaml


If you are trying to only serialize then pprint may also be a good option. It requires the object to be serialized and a file stream.

Here's some code:

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

I am not sure if we can deserialize easily. I was using json to serialize and deserialze earlier which works correctly in most cases.

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

However, in one particular case, there were some errors writing non-unicode data to json.

참고URL : https://stackoverflow.com/questions/4342176/how-do-i-serialize-a-python-dictionary-into-a-string-and-then-back-to-a-diction

반응형