Python数据持久化

3
每当需要存储或通过网络发送Python对象时,它首先进行序列化。我猜这是因为存储和网络传输都基于比特。我有一个愚蠢的问题,更像是计算机科学基础问题而不是Python问题。当Python对象在缓存中时,它们采用什么样的格式?难道它们不应该表示为比特吗?如果是这样,为什么不直接使用这些比特来存储或发送对象,而要费心进行序列化?

1
一个快速的答案:你提到的将高度依赖于平台。 - starrify
@starrify。你能否更详细地解释一下这个问题,或者给我推荐一篇讲得比较好的文章或书籍?谢谢! - David Zheng
2个回答

3

比特表示

同一对象在不同机器上的 表示可能会不同:

  • 考虑 字节序(大小端)
  • 架构(32 位,64 位)

因此,在发送方机器上的对象表示可以意味着在接收方上什么都没有(或更糟的是,可能意味着其他内容)。

以简单整数1025为例说明这个问题:

  • 在字节序为 Big Endian 的机器上, 表示为:
    • 二进制: 00000000 00000000 00000100 00000001
    • 十六进制: 0x00000401
  • 而在字节序为 Little Endian 的机器上,则为:
    • 二进制: 00000001 00000100 00000000 00000000
    • 十六进制: 0x01040000

这就是为什么两台机器必须达成协议、约定。例如,对于IP协议,约定使用网络字节序(big-endian)。

关于字节序可以在这个问题中了解更多。

序列化(和反序列化)

我们无法直接将一个对象的基础 位表示 发送到网络上,原因如上所述,但不仅如此。

一个对象可以通过指针(第二个对象的内存地址)在内部引用另一个对象。此地址再次取决于平台。

Python 使用一种称为 pickling 的序列化算法来解决这个问题,该算法将对象层次结构转换为字节流。当这个字节流通过网络发送时,它仍然是平台相关的,因此需要协议以便于两端互相理解。

Pickle 模块文档


这是否意味着Python序列化,例如pickle过程将位转换为另一种格式的位,可被所有机器普遍理解?从高层次上讲,您能否介绍一下实现方式? - David Zheng
@David 我更新了我的回答,并简要解释了Python中的序列化方式,即pickling。 - arainone
刚刚按照您的建议,将评论分成了两部分。为了更好地理解这个想法,我可以做一个类比。使用不同位表示的机器就像两个国家使用不同的长度单位一样。例如,A国使用英尺,B国使用步幅。两个国家都知道如何在自己的单位和通用的长度单位米之间进行转换。A国要求B国制造一件长1英尺的东西是不可能的,因为B国没有人知道1英尺有多长。 - David Zheng
续上一条评论。为了实现这一点,A国需要首先将长度转换为米(腌制)。然后B国可以将该长度从米转换为步幅(解腌),并开始生产。长度单位转换类似于腌制协议。我理解的正确吗? - David Zheng
@David,你的比喻对于字节序问题是正确的,米表示网络字节顺序,米是一种双方都知道如何进行转换的单位。但是对于pickle来说,做出这样的类比会过于简单化问题,特别是因为pickling将对象层次结构转换为字节流。我建议你阅读pickle文档来更好地理解pickle的含义。 - arainone

1
I/O的关键点在于实现互操作性,例如你通过网络发送的JSON可能需要通过HTTP协议传输,然后由JavaScript解析。而你存储在磁盘上的数据可能需要在下一次运行Python时可读(不同的运行环境、内存分配等)。
但是对于代码执行来说,通常希望实现比使用可互操作格式更高的性能, 例如使用内存位置地址来访问对象方法、字典项等,或尽可能优化处理器缓存
有关Python如何实现的详细信息,可以查看其中一个解释器实现

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接