在Python中使用 metaclasses/反射从UDP缓冲区获取对象类型
有没有办法从在Python中通过UDP套接字接收到的消息中提取对象的类型或类名,使用元类或反射技术?
场景是这样的:
在一个套接字上接收UDP数据包。
这个UDP数据包是一个序列化的二进制字符串(也就是一条消息)。但此时我们并不知道这条消息的类型,所以无法将其反序列化成合适的消息。
我的问题是,我能否知道这个序列化的二进制字符串(作为UDP数据包接收到的)对应的类名,这样我就可以将其反序列化成合适的消息并进一步处理。
提前谢谢你。
3 个回答
更新后的回答,针对更新的问题:
“但是此时不知道消息的类型。所以无法反序列化成合适的消息。”
你得到的是一串字节。如何解读这串字节,取决于你使用的协议是什么。只有你自己知道你用的是什么协议。所以如果你不知道消息的类型,那就没办法处理了。如果你要接收一串数据并进行解读,你必须知道这些数据的含义,否则你就无法理解它。
就是这么简单。
“现在,我的问题是我能知道序列化的二进制字符串的类名吗?”
可以。类名是“str”,就像所有的字符串一样。(除非你使用的是Python 3,这样你得到的就不是str,而是二进制数据)。这个str里面的数据没有类名。它只是二进制数据,意味着发送者想让它意味着什么就是什么。
再次强调,你不应该把这个问题变得太笼统。请具体说明你想做什么,而不是泛泛而谈。
从UDP套接字接收到的内容是一个字节串——这就是你实际得到的“对象类型或类名”。如果这个字节串是通过某种方式序列化的对象(比如用pickle
或者marshal
等),那么你可以把它反序列化回对象(比如用pickle.loads
),然后就可以随意查看里面的内容了。但大多数字节串是用其他方式生成的,当你尝试从中用loads
反序列化时,可能会出现错误。
编辑:原作者的编辑提到这个字符串是“一个序列化的对象”,但仍然没有说明是用什么序列化方法生成的,这一点非常重要。pickle
(还有一种更窄范围的类型marshal
)在它们生成的字符串中包含了足够的信息(通过模块的.dumps
函数),以便它们各自的loads
函数可以正确地反序列化回相应的类型;但其他方法(比如struct.pack
)在生成的字符串中没有这样的元数据,所以没有额外的“外部”信息的话,就无法反序列化。因此,原作者,这个字节串最开始是怎么序列化的呢……?