VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • Python3标准库:pickle对象串行化

作者:@小灰灰
本文为作者原创,转载请注明出处:https://www.cnblogs.com/liuhui0308/p/12504654.html


回到顶部(go to top)

1. pickle对象串行化

pickle模块实现了一个算法可以将任意的Python对象转换为一系列字节。这个过程也被称为串行化对象。可以传输或存储表示对象的字节流,然后再重新构造来创建有相同性质的新对象。

1.1 编码和解码字符串中的数据

第一个例子使用dumps()将一个数据结构编码为一个字符串,然后把这个字符串打印到控制台。它使用了一个完全由内置类型构成的数据结构。任何类的实例都可以pickled,如后面的例子所示。


	
  1. import pickle
  2. import pprint
  3.  
  4. data = [{'a': 'A', 'b': 2, 'c': 3.0}]
  5. print('DATA:', end=' ')
  6. pprint.pprint(data)
  7.  
  8. data_string = pickle.dumps(data)
  9. print('PICKLE: {!r}'.format(data_string))

默认的,pickle将以一种二进制格式写入,在Python 3程序之间共享时这种格式兼容性最好。

数据串行化后,可以写到一个文件、套接字、管道或者其他位置。之后可以读取这个文件,将数据解除pickled,以便用同样的值构造一个新对象。


	
  1. import pickle
  2. import pprint
  3.  
  4. data1 = [{'a': 'A', 'b': 2, 'c': 3.0}]
  5. print('BEFORE: ', end=' ')
  6. pprint.pprint(data1)
  7.  
  8. data1_string = pickle.dumps(data1)
  9.  
  10. data2 = pickle.loads(data1_string)
  11. print('AFTER : ', end=' ')
  12. pprint.pprint(data2)
  13.  
  14. print('SAME? :', (data1 is data2))
  15. print('EQUAL?:', (data1 == data2))

新构造的对象等于原来的对象,但并不是同一个对象。

1.2 处理流

除了dumps()和loads(),pickle还提供了一些便利函数来处理类似文件的流。可以向一个流写多个对象,然后从流读取这些对象,而无须事先知道要写多少个对象或者这些对象多大。


	
  1. import io
  2. import pickle
  3.  
  4. class SimpleObject:
  5.  
  6. def __init__(self, name):
  7. self.name = name
  8. self.name_backwards = name[::-1]
  9. return
  10.  
  11. data = []
  12. data.append(SimpleObject('pickle'))
  13. data.append(SimpleObject('preserve'))
  14. data.append(SimpleObject('last'))
  15.  
  16. # Simulate a file.
  17. out_s = io.BytesIO()
  18.  
  19. # Write to the stream
  20. for o in data:
  21. print('WRITING : {} ({})'.format(o.name, o.name_backwards))
  22. pickle.dump(o, out_s)
  23. out_s.flush()
  24.  
  25. # Set up a read-able stream
  26. in_s = io.BytesIO(out_s.getvalue())
  27.  
  28. # Read the data
  29. while True:
  30. try:
  31. o = pickle.load(in_s)
  32. except EOFError:
  33. break
  34. else:
  35. print('READ : {} ({})'.format(
  36. o.name, o.name_backwards))

这个例子使用两个BytesIO缓冲区来模拟流。第一个缓冲区接收pickled的对象,它的值被填入第二个缓冲区,load()读取这个缓冲区。简单的数据库格式也可以使用pickle来存储对象。shelve模块就是这样一个实现。

除了存储数据,pickle对于进程间通信也很方便。例如,os.fork()和os.pipe()可以用来建立工作进程,从一个管道读取作业指令,并把结果写至另一个管道。管理工作线程池以及发送作业和接收响应的核心代码可以重用,因为作业和响应对象不必基于一个特定的类。使用管道或套接字时,在转储各个对象之后不要忘记刷新输出,以便将数据通过连接推送到另一端。参见multiprocessing模块来了解一个可重用的工作线程池管理器。

1.3 重构对象的问题

处理定制类时,pickled的类必须出现在读取pickle的进程所在的命名空间里。只会pickled这个实例的数据,而不是类定义。类名用于查找构造函数,以便在解除pickled时参见新对象。下面这个例子将一个类的实例写至一个文件。


	
  1. import pickleclass SimpleObject:
  2.  
  3. def __init__(self, name):
  4. self.name = name
  5. l = list(name)
  6. l.reverse()
  7. self.name_backwards = ''.join(l)
  8.  
  9. if __name__ == '__main__':