我一直在使用解析模块construct,并且发现自己真的很迷恋它的数据结构的声明性质。对于那些不熟悉它的人,你可以编写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,
),
)
虽然construct并不真正支持在这个结构中存储值(你可以将抽象Container解析为字节流或将字节流解析为抽象容器),我想扩展框架,以便解析器也可以存储值解析,以便用点符号 ethernet.type 访问它们。
但是这样做,认为这里最好的解决方案是编写编码/解码机制的通用方法,这样你就可以注册编码/解码机制,并能够从抽象数据结构中产生各种输出(解析器本身),以及解析器的输出。
举个例子,默认情况下,当您运行通过解析器打包的以太网时,最终会出现类似dict的内容:
Container(name='ethernet_header',
destination='\x01\x02\x03\x04\x05\x06',
source='\x01\x02\x03\x04\x05\x06',
type=IPX
)
我不想要解析两次 - 我希望解析器能够以可配置的方式生成'target'对象/字符串/字节。
这个想法的根源在于你可以为消费或处理结构注册各种“插件”,这样你就可以以编程方式生成XML或Graphviz图,以及能够从字节转换为Python dicts。任务的关键是,走一个节点树并基于编码器/解码器,转换并返回转换后的对象。
所以问题基本上是 - 哪种模式最适合此目的?
<小时/>
我查看了编解码器模块,它非常优雅,因为您创建了编码机制,注册您的类可以对事物进行编码,并且您可以动态指定所需的特定编码。
'blah blah'.encode('utf8')
<小时/>
现在有几个用于Python的现有serdes模块的例子,我想起了JSON - 但它的问题在于它非常具体,并且不容易支持任意格式。你可以编码或解码JSON,基本上就是这样。有像这样构造的各种serdes,有些使用加载,* 转储 *方法,有些则没有。这是一个废话。
objects = json.loads('{'a': 1, 'b': 2})
<小时/>
我对访问者模式并不十分熟悉,但似乎确实有一些可能适用的机制 - 这个想法(如果我理解正确的话),你就设置了节点的访问者并且它' d走树然后应用一些转换(并返回新的对象?)..我在这里很朦胧。
是否有其他机制可能更加pythonic或已经写入?我考虑过使用ElementTree和子类化Elements - 但是我想在做一些愚蠢的事情之前先咨询stackoverflow。