MessagePack is an efficient binary serialization format. It lets you exchange data among multiple languages like JSON. But it's faster and smaller. This package provides CPython bindings for reading and writing MessagePack data.
$ pip install msgpack
The extension module in msgpack (msgpack._cmsgpack) does not support PyPy.
But msgpack provides a pure Python implementation (msgpack.fallback) for PyPy.
If you can't use a binary distribution, you need to install Visual Studio or the Windows SDK on Windows. Without the extension, the pure Python implementation on CPython runs slowly.
Use packb for packing and unpackb for unpacking.
msgpack provides dumps and loads as aliases for compatibility with
json and pickle.
pack and dump pack to a file-like object.
unpack and load unpack from a file-like object.
>>> import msgpack
>>> msgpack.packb([1, 2, 3])
'\x93\x01\x02\x03'
>>> msgpack.unpackb(_)
[1, 2, 3]Read the docstring for options.
Unpacker is a "streaming unpacker". It unpacks multiple objects from one
stream (or from bytes provided through its feed method).
import msgpack
from io import BytesIO
buf = BytesIO()
for i in range(100):
buf.write(msgpack.packb(i))
buf.seek(0)
unpacker = msgpack.Unpacker(buf)
for unpacked in unpacker:
print(unpacked)It is also possible to pack/unpack custom data types. Here is an example for
datetime.datetime.
import datetime
import msgpack
useful_dict = {
"id": 1,
"created": datetime.datetime.now(),
}
def decode_datetime(obj):
if '__datetime__' in obj:
obj = datetime.datetime.strptime(obj["as_str"], "%Y%m%dT%H:%M:%S.%f")
return obj
def encode_datetime(obj):
if isinstance(obj, datetime.datetime):
return {'__datetime__': True, 'as_str': obj.strftime("%Y%m%dT%H:%M:%S.%f")}
return obj
packed_dict = msgpack.packb(useful_dict, default=encode_datetime)
this_dict_again = msgpack.unpackb(packed_dict, object_hook=decode_datetime)Unpacker's object_hook callback receives a dict; the
object_pairs_hook callback may instead be used to receive a list of
key-value pairs.
NOTE: msgpack can encode datetime with tzinfo into standard ext type for now.
See datetime option in Packer docstring.
It is also possible to pack/unpack custom data types using the ext type.
>>> import msgpack
>>> import array
>>> def default(obj):
... if isinstance(obj, array.array) and obj.typecode == 'd':
... return msgpack.ExtType(42, obj.tostring())
... raise TypeError("Unknown type: %r" % (obj,))
...
>>> def ext_hook(code, data):
... if code == 42:
... a = array.array('d')
... a.fromstring(data)
... return a
... return ExtType(code, data)
...
>>> data = array.array('d', [1.2, 3.4])
>>> packed = msgpack.packb(data, default=default)
>>> unpacked = msgpack.unpackb(packed, ext_hook=ext_hook)
>>> data == unpacked
TrueAs an alternative to iteration, Unpacker objects provide unpack,
skip, read_array_header, and read_map_header methods. The former two
read an entire message from the stream, respectively deserializing and returning
the result, or ignoring it. The latter two methods return the number of elements
in the upcoming container, so that each element in an array, or key-value pair
in a map, can be unpacked or skipped individually.
Early versions of msgpack didn't distinguish string and binary types. The type for representing both string and binary types was named raw.
You can pack into and unpack from this old spec using use_bin_type=False
and raw=True options.
>>> import msgpack
>>> msgpack.unpackb(msgpack.packb([b