2016-03-08 2 views
2

Моей структуры данных, как это:Используя msgpack-питон с вложенным namedtuples

user = UserTuple(
    name=u'Anakin', surname=u'Skywalker', birthdate=datetime.date(1981, 7, 25), 
    profile=ProfileTuple(avatar=u'http://localhost/profile.jpg') 
) 

И я хочу, чтобы упаковать эти данные с модулем msgpack-питоном. Но msgpack конвертирует namedtuples в списки. Может быть возможным пакет данных данных, как это с msgpack и сохранить namedtuples, так же, как pickle/cpickle?

ответ

4

Вы должны иметь последнюю версию msgpack-python. v0.4.7 не работает. (В настоящее время необходимо установить из мастер-ветки).

import msgpack 
from collections import namedtuple 

User = namedtuple('User', ['name', 'profile']) 
Profile = namedtuple('Profile', ['avatar']) 

def ext_pack(x): 
    if isinstance(x, User): 
     return msgpack.ExtType(1, msgpack.packb([x[0], x[1]], default=ext_pack, strict_types=True)) 
    elif isinstance(x, Profile): 
     return msgpack.ExtType(2, msgpack.packb(x[0], default=ext_pack, strict_types=True)) 
    return x 

def ext_unpack(code, data): 
    if code == 1: 
     name, profile = msgpack.unpackb(data, ext_hook=ext_unpack) 
     return User(name, profile) 
    elif code == 2: 
     avatar = msgpack.unpackb(data, ext_hook=ext_unpack) 
     return Profile(avatar) 
    return msgpack.ExtType(code, data) 

x = User("me", Profile(234)) 
s = msgpack.packb([x, [1, x]], default=ext_pack, strict_types=True) 
msgpack.unpackb(s, ext_hook=ext_unpack) 
>>> [User(name='me', profile=Profile(avatar=234)), 
[1, User(name='me', profile=Profile(avatar=234))]] 

Здесь мы помечать User, Profile как тип кода 1, 2 соответственно. Кроме того, вы можете обрабатывать все namedtuple как код того же типа и сохранять фактические типы в полях данных.