我一直在使用解析模块构造,并且发现自己非常喜欢它的数据结构的声明性。对于那些不熟悉它的人,您可以编写 Python 代码,这些代码基本上看起来像您在实例化时通过嵌套对象尝试解析的内容。
例子:
ethernet = Struct("ethernet_header",
Bytes("destination", 6),
Bytes("source", 6),
Enum(UBInt16("type"),
IPv4 = 0x0800,
ARP = 0x0806,
RARP = 0x8035,
X25 = 0x0805,
IPX = 0x8137,
IPv6 = 0x86DD,
),
)
虽然构造并不真正支持在此结构中存储值(您可以将抽象容器解析为字节流或将字节流解析为抽象容器),但我想扩展框架,以便解析器也可以在解析时存储值所以可以以点符号ethernet.type访问它们。
但是在这样做时,认为最好的解决方案是编写编码/解码机制的通用方法,以便您可以注册编码/解码机制并能够从抽象数据结构(解析器本身),以及解析器的输出。
举个例子,默认情况下,当您运行通过解析器打包的以太网时,您最终会得到类似 dict 的东西:
Container(name='ethernet_header',
destination='\x01\x02\x03\x04\x05\x06',
source='\x01\x02\x03\x04\x05\x06',
type=IPX
)
我不想解析两次 - 理想情况下,我希望解析器以可配置的方式生成“目标”对象/字符串/字节。
这个想法的根源是您可以注册各种“插件”以使用或处理结构,以便您可以以编程方式生成 XML 或 Graphviz 图表以及能够从字节转换为 Python 字典。任务的关键是,遍历节点树并基于编码器/解码器,转换并返回转换后的对象。
所以问题本质上是——什么模式最适合这个目的?
编解码器风格:
我查看了编解码器模块,它相当优雅,因为您可以创建编码机制,注册您的类可以对事物进行编码,并且您可以即时指定您想要的特定编码。
'blah blah'.encode('utf8')
serdes(序列化器,反序列化器):
有几个 Python 的现有 serdes 模块的例子,我脑海中浮现出 JSON ——但它的问题是它非常具体,不能轻易支持任意格式。您可以对 JSON 进行编码或解码,基本上就是这样。像这样构造的 serdes 有很多种,有些使用load、* dumps * 方法,有些则不使用。这是一个废话。
objects = json.loads('{'a': 1, 'b': 2})
访客模式(?):
我对访问者模式不是很熟悉,但它似乎有一些可能适用的机制——想法是(如果我理解正确的话),你会为节点设置一个访问者,它会走树并应用一些转换(并返回新对象?)..我在这里很模糊。
其他?:
是否有其他机制可能更 Pythonic 或已经编写?我考虑过可能使用 ElementTree 和子类化元素 - 但我想在做一些愚蠢的事情之前咨询 stackoverflow。