js 对象序列化,python 对象序列化

  js 对象序列化,python 对象序列化

  我们想把最近爬虫得到的下载结果存档。这个结果是计算机编程语言对象。我不打算简单地保存超文本标记语言或json,而是想让整个下载过程都能恢复。因此,我们考虑使用计算机编程语言内置的泡菜库(腌菜黄瓜库),将序列化对象定为字节,可以根据需要进行反序列化。

  通过以下代码可以轻松了解泡菜的使用方法和功能。

  一

  2

  3

  四

  5

  6

  七

  8

  9

  10

  11

  12

  13

  14

  15

  16

  17

  18

  19

  20

  21

  22

  23

  24

  25

  26

  27

  28

  29

  30

  31

  32

  33

  34

  35

  36

  37

  38

  39

  40

  41

  42

  43

  44

  45

  46

  47

  48

  49

  50

  51

  52

  53

  54

  55

  56

  57

  58

  59

  60

  61

  62

  在[2]中:导入泡菜

  在[3]答中:类:通过。

  在[4]中:a=A(

  In[5]:a.foo=hello

  在[6]中:a.bar=2

  in [7] : pick _ ed=pickle.dumps(一个(

  在[8]:挑选

  out[8]:b \ X80 \ x03c _ main _ _ na _ NQ _ x00()x81q \ x01)q x02(x x03)x00)))

  in[9]:un pick=pickle。loads(pick _ ed))))))。

  在[10]:取消拾取

  out [ 10 ] : _ _ main _.aat0x 10a e 67278

  在[11]中

  out [ 11 ] : _ _ main _.aat0x 10a e 67128

  in[12]:dir(unpick))。

  Out[12]:

  [__class__ ,

  __delattr__ ,

  __dict__ ,

  __dir__ ,

  __doc__ ,

  __eq__ ,

  __format__ ,

  __ge__ ,

  __getattribute__ ,

  __gt__ ,

  __hash__ ,

  __init__ ,

  __init_subclass__ ,

  __le__ ,

  __lt__ ,

  __模块_ _ ,

  __ne__ ,

  __new__ ,

  __reduce__ ,

  __reduce_ex__ ,

  __repr__ ,

  __setattr__ ,

  __sizeof__ ,

  __slotnames__ ,

  __str__ ,

  __subclasshook__ ,

  __weakref__ ,

  酒吧,

  foo]

  In[13]:unpick.foo

  Out[13]:”你好"

  In[14]:unpick.bar

  Out[14]:2

  您会发现泡菜的用法与数据有点相似,但有几个根本的区别:

  数据是语言间通用的数据交换形式,一般用文本表示,可供人类阅读泡菜。用于序列化计算机编程语言对象。但是,对于Python,序列化的结果是二进制数据,人类无法读取。然后,json缺省情况下只能序列化某些内置类型,而泡菜可以序列化相当多的数据。

  另一个旧整理也内置其中。但是,这个库主要针对。力兴文件。不支持自定义类型,并且不完整。例如,如果无法处理循环APP,并且有引用自己的对象,则使用整理时计算机编程语言解释器会挂起。

  版本兼容问题

  由于泡菜是针对计算机编程语言的,Python有不同的版本(并且2与3之间差异非常大),所以就要考虑到序列化出来的对象能不能被更高(或低?)版本的计算机编程语言反序列化出来。

  目前一共有5个泡菜的协议版本,版本越高对应皮顿的版本越高,0-2针对蟒蛇皮2,3-4针对Python3 .

  协议版本0是原始的"人类可读"协议,并向后兼容早期版本的Python .

  协议版本一是一种旧的二进制格式,也与计算机编程语言的早期版本兼容。

  Python 2.3中引入了协议版本2。它提供了更有效的新型类的酸洗。有关协议2带来的改进的信息,请参考EP 307 .(从这个版本往后,性能有显著提高)

  Python 3.0中添加了协议版本3。它显式支持对于目标来说,并且不能被Python 2.x取消拾取。这是默认协议,并且在需要与其他Python 3版本兼容时是推荐的协议。

  Python 3.4中添加了协议版本4。它增加了对非常大的对象的支持,支持更多种类的对象,以及一些数据格式优化。有关协议四带来的改进的信息,请参考欧洲专利3154号.

  泡菜的大多数入口函数(例如dump(),转储(),选取器构造器)都接受一个协议版本的参数,其中内置了两个变量:

  泡菜。最高_协议目前是四

  泡菜。默认_协议目前是3

  用法

  类似于内置的json模块接口,dump()用于返回序列化结果,dump()用于序列化然后写入文件。类似的还有loads()和loads()。其中,可以在序列化转储时指定协议的版本,但不能在反序列化时指定,版本将被自动识别。这非常类似于zip命令。

  内置类型的序列化

  大多数内置类型支持序列化和反序列化。要特别注意功能。一个函数的序列化只需要它的名字和它所在的模块。函数的代码和属性(Python的函数是一级对象,可以有属性)不会序列化。这就要求函数所在的模块在unpickle环境下必须是可导入的,否则就会出现ImportError或AttributeError。

  这里有个有趣的事情:所有的lambda函数都不是Pickle。因为他们的名字叫。

  自定义类型的序列化

  就像本文开头的实验代码一样,在大多数情况下,我们不需要额外的操作就可以实现自定义对象的序列化/反序列化。需要注意的是,在反序列化的过程中,并不是调用class的__init__()来初始化一个对象,而是创建一个新的未初始化的实例,然后恢复其属性(非常巧妙)。伪代码如下:

  一个

  2

  三

  四

  五

  六

  七

  defsave(obj):

  return(obj。__class__,obj。__字典_ _)

  defload(cls,属性):

  obj=cls。__新__(cls)

  obj。__词典_ _。更新(属性)

  returnobj

  如果想在序列化的过程中做一些额外的操作,比如保存对象的状态,可以使用pickle协议的神奇方法,最常见的有__setstate__()和__getstate__()。

  安全问题(!)

  在unpickle文档的开始,它说:永远不要解包一个未知来源的二进制文件。考虑以下代码:

  一个

  2

  三

  四

  进口泡菜

  pickle . loads(b cos \ n system \ n(S echo hello world \ ntR。)

  编译

  0

  当这段代码解钩时,它导入os.system(),然后调用echo。没有副作用。但是如果是rm -rf /?

  文档中给出的建议是在Unpickler.find_class()中实现检查逻辑。当需要全局变量时,必须调用方法。

  一个

  2

  三

  四

  五

  六

  七

  八

  九

  10

  11

  12

  13

  14

  15

  16

  17

  18

  19

  20

  21

  22

  23

  24

  25

  导入内置项

  进口

  进口泡菜

  safe_builtins={

  范围,

  复杂,

  设置,

  冰冻集,

  切片,

  }

  classRestrictedUnpickler(泡菜。拆线工):

  deffind_class(自身,模块,名称):

  #只允许内置的安全类。

  if module== builtins and nameinsafe _ builtins:

  returngetattr(内置,名称)

  #禁止其他一切。

  raisepickle。UnpicklingError(禁止使用全局 %s.%s )

  (模块,名称))

  defrestricted _负载:

  类似于pickle.loads()的辅助函数。

  returnRestrictedUnpickler(io。字节)。负载()

  压缩

  之后Pickle不会自动压缩。我觉得这个设计很好。解耦,pickle做pickle做的,压缩交给其他库。而且你还可以发现pickle之后的文件无法读取,但是内容还是以ascii码呈现,并不是乱码。您需要调用压缩库的compress。实际压缩后体积是之前的1/3左右,非常可观。

  我目前知道的坑:

  保持全局变量的可导入性有点困难。要面对的问题是:我今天腌制的东西,需要在未来的某一天打开。还能打开吗?

  这里有几个版本:项目的版本,python的版本,pickle协议的版本,项目依赖的包版本。python版本和pickle版本很容易解决,我认为我可以放心地依赖它们的向后兼容性。它是主项目和版本以及从属版本。如果要备份的对象非常复杂,旧版本的备份可能无法与新版本兼容。可能的解决方案是完全锁定所有依赖项,比如记录它们的哈希值。如果要还原某个二进制序列,就要还原当时的具体依赖和项目的具体提交。

  但是现在,我们的要求基本上是一个请求。响应对象。我认为我们可以依靠它们的向后兼容性。如果有一天请求有了突破性的改变,那么即使我们的泡菜是兼容的,代码也不会是兼容的。这时候就可以考虑其他策略了。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: