【问题标题】:Q on Python serialization/deserialization关于 Python 序列化/反序列化的 Q
【发布时间】:2010-03-31 19:01:08
【问题描述】:

我有什么机会实例化、保留和序列化/反序列化到/从反映这种模式的二进制数据 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

问候

【问题讨论】:

  • 你为什么不满意?
  • 泡菜有什么问题?为什么在使用 Python 时会关心使用 C++ 的一些深奥的方法?你希望发生什么?看起来您想要一种密集的数据存储方法,但很难说出您真正想要概括的内容。
  • 我必须实现zinfandel.levkowetz.com/html/draft-ietf-p2psip-base-08。希望这说明了一切。我必须满足线路协议,它是二进制的,但不符合 pickle 标准。我对此不满意,因为它不够通用:)

标签: python serialization binary


【解决方案1】:

两个建议:

  1. 对于可变长度结构使用固定格式 然后对结果进行切片。
  2. 使用 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
>>> 

【讨论】:

  • 嗯。感谢您的提示,但 V1 未正确序列化。 “”表示法已从 TLS RFC 中采用。需要在每个可变长度字节数组之前加上一个元素,该元素指示结构的 当前 长度。在 V1 的情况下,预期结果必须类似于我的示例。
  • 我看不出我的 V1 结果与您的结果有何不同(除了我在“你好”中使用了小写的 h)。当前长度包含在结果中:这就是 'p' 格式在 Struct 中所做的。
  • 啊,好的。不知道“p”。谢谢
猜你喜欢
  • 2012-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多