피클 또는 JSON?


114

dict키가 유형 str이고 값이 ints 인 작은 개체 를 디스크에 저장 한 다음 복구해야합니다 . 이 같은:

{'juanjo': 2, 'pedro':99, 'other': 333}

최선의 선택은 무엇이며 그 이유는 무엇입니까? pickle또는로 직렬화하십시오 simplejson.

Python 2.6을 사용하고 있습니다.


무엇으로 변환합니까? 또한 어떤 의미에서 더 나은가 ?
SilentGhost 2010

10
2.6에서는를 사용하지 않고 simplejson내장 json모듈 (정확한 인터페이스가 동일 함)을 사용합니다.
Mike Graham

5
"베스트"? 무엇에 가장 적합합니까? 속도? 복잡성? 적응성? 비용?
S.Lott


답변:


68

상호 운용성 요구 사항이없고 (예 : Python에서 데이터를 사용하려는 경우) 바이너리 형식이 괜찮다면, 정말 빠른 Python 객체 직렬화를 제공 하는 cPickle 을 사용하십시오.

상호 운용성을 원하거나 텍스트 형식으로 데이터를 저장하려면 JSON (또는 제약 조건에 따라 다른 적절한 형식)을 사용하십시오.


48
JSON cPickle보다 빠른 것 같습니다 .
mac

5
내 대답은 두 솔루션 중 하나를 선택할 때 가장 중요하다고 생각하는 문제를 강조합니다. 나는 어느 쪽이 다른 쪽보다 빠르다는 주장을하지 않습니다. JSON이 더 빠르고 적절하다면 JSON으로 가십시오! (즉, 당신의 반대표에 대한 이유가 없습니다.)
Håvard S

10
내 요점은 JSON을 통해 전제를 기반으로 cPickle(또는 pickle) 사용하는 실제 이유가 없다는 것 입니다. 내가 당신의 대답을 처음 읽었을 때 나는 그 이유가 속도 때문이라고 생각했지만 이것은 사실이 아니기 때문에 ... :)
mac

14
@mac에서 인용 한 벤치 마크는 문자열 만 테스트합니다. str, int 및 float를 별도로 테스트 한 결과 json이 float 직렬화를 사용하는 cPickle보다 느리지 만 float 비 직렬화를 사용하면 더 빠릅니다. int (및 str)의 경우 json은 두 가지 모두 더 빠릅니다. 데이터 및 코드 : gist.github.com/marians/f1314446b8bf4d34e782
마리아

24
cPickle의 최신 프로토콜은 이제 JSON보다 빠릅니다. JSON이 더 빠르다는 찬성 의견은 몇 년 전에 구식입니다. stackoverflow.com/a/39607169/1007353
JDiMatteo

104

직렬화를 위해 피클보다 JSON을 선호합니다. Unpickling은 임의의 코드를 실행할 수 pickle있으며 프로그램간에 데이터를 전송하거나 세션간에 데이터를 저장하는 데 사용하는 것은 보안 허점입니다. JSON은 보안 허점을 도입하지 않고 표준화되어 있으므로 필요한 경우 다른 언어로 된 프로그램에서 데이터에 액세스 할 수 있습니다.


감사. 어쨌든 나는 같은 프로그램에서 덤핑하고 로딩 할 것이다.
Juanjo Conti

2
현재 애플리케이션에서는 보안 위험이 낮을 수 있지만 JSON을 사용하면 전체를 모두 닫을 수 있습니다.
Mike Graham

4
로드 후 피클하는 모든 것에 피클하는 피클 바이러스를 만들 수 있습니다. json으로는 불가능합니다.
User

2
보안 외에도 JSON은 마이그레이션을 쉽게한다는 추가적인 이점이 있으므로 이전 버전의 애플리케이션에서 저장 한 데이터를로드 할 수 있습니다. 한편 필드를 추가하거나 전체 하위 구조를 대체 할 수 있습니다. dict / list에 대한 이러한 변환기 (마이그레이션)를 작성하는 것은 간단하지만 Pickle을 사용하면 변환을 생각하기 전에 처음부터로드하기가 어려울 것입니다.
vog

2
나는이 측면 (보안과 피클 된 객체가 임의의 코드를 실행하는 능력)에 대해 생각하지 않았습니다. 지적 해 주셔서 감사합니다!
CaffeinatedMike

43

몇 가지 차트를 통해 흥미로운 사실을 발견 할 수도 있습니다. http://kovshenin.com/archives/pickle-vs-json-which-is-faster/


1
이 기사는 문자열과 관련된 성능 만 비교합니다. 다음은 별도로 테스트 문자열, 수레와의 int하기 위해 실행할 수있는 스크립트입니다 : gist.github.com/marians/f1314446b8bf4d34e782
마리아


20

주로 속도와 공간에 관심이 있다면 cPickle이 JSON보다 빠르기 때문에 cPickle을 사용하십시오.

상호 운용성, 보안 및 / 또는 사람의 가독성에 더 관심이 있다면 JSON을 사용하십시오.


다른 답변에서 참조 된 테스트 결과는 2010 년에 기록되었으며 2016 년 cPickle 프로토콜 2를 사용한 업데이트 된 테스트 는 다음을 보여줍니다.

  • cPickle 3.8 배 빠른 로딩
  • cPickle 1.5 배 더 빠른 읽기
  • c 약간 더 작은 인코딩 선택

다른 답변에서 참조 된 Konstantin의 벤치 마크를 기반으로 하지만 pickle 대신 프로토콜 2와 함께 cPickle을 사용하고 simplejson 대신 json을 사용 하는 이 요점으로 직접 재현하십시오 ( json이 simplejson보다 빠르기 때문에 ).

wget https://gist.github.com/jdimatteo/af317ef24ccf1b3fa91f4399902bb534/raw/03e8dbab11b5605bc572bc117c8ac34cfa959a70/pickle_vs_json.py
python pickle_vs_json.py

괜찮은 2015 Xeon 프로세서에서 Python 2.7을 사용한 결과 :

Dir Entries Method  Time    Length

dump    10  JSON    0.017   1484510
load    10  JSON    0.375   -
dump    10  Pickle  0.011   1428790
load    10  Pickle  0.098   -
dump    20  JSON    0.036   2969020
load    20  JSON    1.498   -
dump    20  Pickle  0.022   2857580
load    20  Pickle  0.394   -
dump    50  JSON    0.079   7422550
load    50  JSON    9.485   -
dump    50  Pickle  0.055   7143950
load    50  Pickle  2.518   -
dump    100 JSON    0.165   14845100
load    100 JSON    37.730  -
dump    100 Pickle  0.107   14287900
load    100 Pickle  9.907   -

피클 프로토콜 3을 사용하는 Python 3.4는 더 빠릅니다.


11

JSON 또는 피클? JSON 피클 은 어떻습니까 ! 사용할 수 있습니다 jsonpickle. 사용하기 쉽고 디스크의 파일은 JSON이기 때문에 읽을 수 있습니다.

http://jsonpickle.github.com/


2
옵션에 대한 성능을 벤치마킹 한 사람이 있습니까? 여기 benfrederickson.com/dont-pickle-your-data에서 볼 수 있듯이 성능면에서 원시 json과 비슷 합니까?
Josep Valls

이것은 광범위한 벤치 마크는 아니지만 pickle (python3)을 사용하여 레벨을 저장하는 기존 게임이있었습니다. 인간이 읽을 수있는 측면을 위해 jsonpickle을 시도하고 싶었지만 레벨 저장은 슬프게도 훨씬 느 렸습니다. jsonpickle의 경우 1597ms, 레벨 저장시 88ms 또는 일반 피클. 레벨로드의 경우 jsonpickle의 경우 1604ms, pickle의 경우 388입니다. 인간이 읽을 수있는 저장을 좋아하는 유감입니다.
Neil McGill

나는 이것을 우리의 거래 시스템에서 테스트했는데, 가독성은 피클에 비해 약 2 배의 직렬화 + 역 직렬화 속도 패널티와 함께 ​​제공됩니다. 그러나 다른 모든 것에 좋습니다.
nurettin

6

몇 가지 방법을 시도한 결과 덤프 방법의 프로토콜 인수를 다음과 같이 설정하여 cPickle을 사용하는 cPickle.dumps(obj, protocol=cPickle.HIGHEST_PROTOCOL)것이 가장 빠른 덤프 방법 이라는 것을 알았습니다 .

import msgpack
import json
import pickle
import timeit
import cPickle
import numpy as np

num_tests = 10

obj = np.random.normal(0.5, 1, [240, 320, 3])

command = 'pickle.dumps(obj)'
setup = 'from __main__ import pickle, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("pickle:  %f seconds" % result)

command = 'cPickle.dumps(obj)'
setup = 'from __main__ import cPickle, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("cPickle:   %f seconds" % result)


command = 'cPickle.dumps(obj, protocol=cPickle.HIGHEST_PROTOCOL)'
setup = 'from __main__ import cPickle, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("cPickle highest:   %f seconds" % result)

command = 'json.dumps(obj.tolist())'
setup = 'from __main__ import json, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("json:   %f seconds" % result)


command = 'msgpack.packb(obj.tolist())'
setup = 'from __main__ import msgpack, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("msgpack:   %f seconds" % result)

산출:

pickle         :   0.847938 seconds
cPickle        :   0.810384 seconds
cPickle highest:   0.004283 seconds
json           :   1.769215 seconds
msgpack        :   0.270886 seconds

4

개인적으로 저는 데이터가 사람이 읽을 수 있기 때문에 일반적으로 JSON을 선호합니다 . 확실히, JSON이 취할 수없는 것을 직렬화해야한다면 pickle을 사용하십시오.

그러나 대부분의 데이터 저장소에서는 이상한 것을 직렬화 할 필요가 없으며 JSON은 훨씬 더 쉽고 항상 텍스트 편집기에서 열어 데이터를 직접 확인할 수 있습니다.

속도는 좋지만 대부분의 데이터 세트에서 그 차이는 미미합니다. 파이썬은 일반적으로 어쨌든 너무 빠르지 않습니다.



1
진실. 그러나 100목록에있는 요소의 경우 그 차이는 사람의 눈으로 완전히 무시할 수 있습니다. 더 큰 데이터 세트로 작업 할 때 확실히 다릅니다.
rickcnagy 2014
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.