关于Python序列化/反序列化的问题
我想知道我有多大的机会去创建、保存并将Python类的实例转换成二进制数据,这些类遵循这个模式(这个模式来自RFC 2246 [TLS]):
enum { apple, orange } VariantTag;
struct {
uint16 number;
opaque string<0..10>; /* variable length */
} V1;
struct {
uint32 number;
opaque string[10]; /* fixed length */
} V2;
struct {
select (VariantTag) { /* value of selector is implicit */
case apple: V1; /* VariantBody, tag = apple */
case orange: V2; /* VariantBody, tag = orange */
} variant_body; /* optional label on variant */
} VariantRecord;
基本上,我需要定义一个(变体)类叫做VariantRecord,这个类的内容会根据VariantTag的值而变化。这并不难。真正的挑战是找到一种最通用的方法来构建一个类,使其能够将数据转换成字节流并再转换回来……像Pickle、Google协议缓冲区、marshal这些都不适用。
我尝试在我的类中明确地定义一个“def serialize”,但效果不太理想,因为它不够通用。
我希望我能清楚地表达这个问题。
如果VariantTag的值是apple,我当前的解决方案看起来是这样的,但我对此并不太满意。
import binascii
import struct
class VariantRecord(object):
def __init__(self, number, opaque):
self.number = number
self.opaque = opaque
def serialize(self):
out = struct.pack('>HB%ds' % len(self.opaque), self.number, len(self.opaque), self.opaque)
return out
v = VariantRecord(10, 'Hello')
print binascii.hexlify(v.serialize())
>> 000a0548656c6c6f
祝好
1 个回答
0
有两个建议:
- 对于可变长度的结构,使用固定格式,然后只需切割结果。
- 使用
struct.Struct
。
例如,如果我理解你的格式没错的话(你提到的示例中出现的长度字节,其他变体中也有吗?)
>>> import binascii
>>> import struct
>>> V1 = struct.Struct(">H10p")
>>> V2 = struct.Struct(">L10p")
>>> def serialize(variant, n, s):
if variant:
return V2.pack(n,s)
else:
return V1.pack(n,s)[:len(s)+3]
>>> print binascii.hexlify(serialize(False, 10, 'hello')) #V1
000a0568656c6c6f
>>> print binascii.hexlify(serialize(True, 10, 'hello')) #V2
0000000a0568656c6c6f00000000
>>>