Don't Pickle Your Data
benfrederickson.com
benfrederickson.com
You also have to write custom (de)serializers if you want to store datetime objects (my personal pet peeve), any of the special python containers... basically any time you want anything other than an object, array, string or number.
Unless I'm dealing with untrusted data sources, or need to interoperate with other languages, I will keep using Pickle.
cPickle gets a list of objects but json gets a list of dictionaries? The cost of converting the objects into the dictionaries is conveniently excluded from the json benchmark.
You should try serializing the same list of dictionaries, use the highest pickle protocol and repost results.
I filed a bug. https://github.com/benfred/bens-blog-code/issues/1
Baseline JSON:
--------------------------------------------------------------------------------
JSON
packTime 0.612724065781 s - 163205.601975 items/s
unpackTime 0.782174110413 s - 127848.772631 items/s
size 174.26637
Baseline cPickle, ascii protocol: --------------------------------------------------------------------------------
cPickle
packTime 2.41442704201 s - 41417.6938297 items/s
unpackTime 0.875658035278 s - 114199.831408 items/s
size 286.26637
cPickle, highest protocol: --------------------------------------------------------------------------------
cPickleHP
packTime 1.02942800522 s - 97141.3245929 items/s
unpackTime 0.583297967911 s - 171438.965162 items/s
size 198.26637
For giggles, I evened the playing field and let cPickle at the same data structure as JSON, ascii protocol and highest protocol: --------------------------------------------------------------------------------
cPickleJsonData
packTime 0.642832040787 s - 155561.629874 items/s
unpackTime 0.478959083557 s - 208786.101847 items/s
size 205.53356
--------------------------------------------------------------------------------
cPickleHPjsonData
packTime 0.285845041275 s - 349839.897708 items/s
unpackTime 0.340456962585 s - 293722.881273 items/s
size 175.26637
My conclusions? Serializing dictionaries is easier than serializing objects, and using a non-ascii protocol offers some obvious benefits. JSON is not obviously better than cPickle when comparing apples to apples.It's also worth noting that comparing the json module to the pure python Pickle module isn't a fair fight either; json is at least partially written in C.
For instance I have implemented enough of it[0] to use in a drop-in replacement for Graphite[1].
[0]: https://github.com/noteed/python-pickle [1]: http://graphite.wikidot.com/
>>> import json
>>> json.dumps(set())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/json/__init__.py", line 231, in dumps
return _default_encoder.encode(obj)
File "/usr/lib/python2.7/json/encoder.py", line 201, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python2.7/json/encoder.py", line 264, in iterencode
return _iterencode(o, 0)
File "/usr/lib/python2.7/json/encoder.py", line 178, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: set([]) is not JSON serializable
>>> from decimal import Decimal
>>> json.dumps(Decimal(1))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/json/__init__.py", line 231, in dumps
return _default_encoder.encode(obj)
File "/usr/lib/python2.7/json/encoder.py", line 201, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python2.7/json/encoder.py", line 264, in iterencode
return _iterencode(o, 0)
File "/usr/lib/python2.7/json/encoder.py", line 178, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: Decimal('1') is not JSON serializableDisagree strongly. You have no idea how complex my graphs of (pretty damn complex) python objects are and how much I value being able to change their organization without having to rewrite the serialization code every time I do so.
Don't fear pickle. Just don't expect it to be secure or amazingly fast.
For a fully general python <-> json serializer/deserializer, you'd need a bunch of extra annotations etc that would make it look very weird compared with what most people expect when they think of json.