在Python中使用 metaclasses/反射从UDP缓冲区获取对象类型

1 投票
3 回答
765 浏览
提问于 2025-04-15 14:39

有没有办法从在Python中通过UDP套接字接收到的消息中提取对象的类型或类名,使用元类或反射技术?

场景是这样的:

  1. 在一个套接字上接收UDP数据包。

  2. 这个UDP数据包是一个序列化的二进制字符串(也就是一条消息)。但此时我们并不知道这条消息的类型,所以无法将其反序列化成合适的消息。

    我的问题是,我能否知道这个序列化的二进制字符串(作为UDP数据包接收到的)对应的类名,这样我就可以将其反序列化成合适的消息并进一步处理。

提前谢谢你。

3 个回答

0

你需要使用一个序列化模块。picklemarshal都是不错的选择。它们提供了一些功能,可以把对象转换成字节流,然后再把字节流转换回来。

0

更新后的回答,针对更新的问题:

“但是此时不知道消息的类型。所以无法反序列化成合适的消息。”

你得到的是一串字节。如何解读这串字节,取决于你使用的协议是什么。只有你自己知道你用的是什么协议。所以如果你不知道消息的类型,那就没办法处理了。如果你要接收一串数据并进行解读,你必须知道这些数据的含义,否则你就无法理解它。

就是这么简单。

“现在,我的问题是我能知道序列化的二进制字符串的类名吗?”

可以。类名是“str”,就像所有的字符串一样。(除非你使用的是Python 3,这样你得到的就不是str,而是二进制数据)。这个str里面的数据没有类名。它只是二进制数据,意味着发送者想让它意味着什么就是什么。

再次强调,你不应该把这个问题变得太笼统。请具体说明你想做什么,而不是泛泛而谈。

2

从UDP套接字接收到的内容是一个字节串——这就是你实际得到的“对象类型或类名”。如果这个字节串是通过某种方式序列化的对象(比如用pickle或者marshal等),那么你可以把它反序列化回对象(比如用pickle.loads),然后就可以随意查看里面的内容了。但大多数字节串是用其他方式生成的,当你尝试从中用loads反序列化时,可能会出现错误。

编辑:原作者的编辑提到这个字符串是“一个序列化的对象”,但仍然没有说明是用什么序列化方法生成的,这一点非常重要。pickle(还有一种更窄范围的类型marshal)在它们生成的字符串中包含了足够的信息(通过模块的.dumps函数),以便它们各自的loads函数可以正确地反序列化回相应的类型;但其他方法(比如struct.pack)在生成的字符串中没有这样的元数据,所以没有额外的“外部”信息的话,就无法反序列化。因此,原作者,这个字节串最开始是怎么序列化的呢……?

撰写回答