Python之pickle模块的使用
1、pickle序列化列表类型
#!/usr/bin/env python3 # encoding: utf-8 import pickle # 列表套字典 data = [{'a': 'A', 'b': 2, 'c': 3.0}] print('数据内容:', end='') # 设置显示结束为空不带回车 print(data) data_string = pickle.dumps(data) # 序列化对象 print(data_string)
运行效果
[root@ mnt]# python3 pickle_string.py 数据内容:[{'a': 'A', 'b': 2, 'c': 3.0}] b'\x80\x03]q\x00}q\x01(X\x01\x00\x00\x00aq\x02X\x01\x00\x00\x00Aq\x03X\x01\x00\x00\x00bq\x04K\x02X\x01\x00\x00\x00cq\x05G@\x08\x00\x00\x00\x00\x00\x00ua.'
2、pickle反序列化即字节转列表
#!/usr/bin/env python3 # encoding: utf-8 import pickle # 列表套字典 data = [{'a': 'A', 'b': 2, 'c': 3.0}] print('原数据', data, '类型:', type(data)) pickle_byte = pickle.dumps(data) # 序列化对象为字节 print('序列化数据内容:', pickle_byte, '类型:', type(pickle_byte)) # 设置显示结束为空不带回车 pickle_object = pickle.loads(pickle_byte) # 反序列化字符串为对象 print('反序列化数据内容:', pickle_object, '类型:', type(pickle_object))
运行效果
[root@ mnt]# python3 pickle_unpickle.py 原数据 [{'a': 'A', 'b': 2, 'c': 3.0}] 类型: <class 'list'> 序列化数据内容: b'\x80\x03]q\x00}q\x01(X\x01\x00\x00\x00aq\x02X\x01\x00\x00\x00Aq\x03X\x01\x00\x00\x00bq\x04K\x02X\x01\x00\x00\x00cq\x05G@\x08\x00\x00\x00\x00\x00\x00ua.' 类型: <class 'bytes'> 反序列化数据内容: [{'a': 'A', 'b': 2, 'c': 3.0}] 类型: <class 'list'>
3、pickle.dump与pickle.load使用io.BytesIO作为缓冲区,实现序列化与反序列化的示例
#!/usr/bin/env python3 # encoding: utf-8 import pickle import io class SimpleObject(object): def __init__(self, name): self.name = name self.name_backwards = name[::-1] # 列表反转 data = [] # 列表存SimpleObject实例化对象 data.append(SimpleObject('pickle')) data.append(SimpleObject('preserve')) data.append(SimpleObject('last')) # 创建一个字节输出缓冲区 out_s = io.BytesIO() print('序列化数据:') for obj in data: print('{} ({})'.format(obj.name, obj.name_backwards)) pickle.dump(obj, out_s) out_s.flush() # 创建一个输入缓冲区 in_s = io.BytesIO(out_s.getvalue()) print('反序列化数据:') while True: try: obj = pickle.load(in_s) except EOFError: break else: print('{} ({})'.format(obj.name, obj.name_backwards))
运行效果
[root@ mnt]# python3 pickle_stream.py 序列化数据: pickle (elkcip) preserve (evreserp) last (tsal) 反序列化数据: pickle (elkcip) preserve (evreserp) last (tsal)
4、pickle序化为到文件中的示例
#!/usr/bin/env python3 # encoding: utf-8 import pickle import io class SimpleObject(object): def __init__(self, name): self.name = name l = list(name) # 把输入的名字反转 l.reverse() self.name_backwards = ''.join(l) data = [] # 列表存SimpleObject实例化对象 data.append(SimpleObject('pickle')) data.append(SimpleObject('preserve')) data.append(SimpleObject('last')) # 创建一个字节输出缓冲区 out_s = io.BytesIO() filename = 'pickle_temp' with open(filename, 'wb') as wf: for obj in data: print('{} ({})'.format(obj.name, obj.name_backwards)) pickle.dump(obj, wf) # 序列化到文件中
运行效果
[root@ mnt]# python3 pickle_dump_to_file.py pickle (elkcip) preserve (evreserp) last (tsal) [root@ mnt]# ll -rw-r--r-- 1 root root 679 Jan 12 11:40 pickle_dump_to_file.py -rw-r--r-- 1 root root 288 Jan 12 11:41 pickle_temp
5、pickle从文件中反序化的示例
#!/usr/bin/env python3 # encoding: utf-8 import pickle # 对象必须存在,不然会报异常 class SimpleObject(object): def __init__(self, name): self.name = name l = list(name) # 把输入的名字反转 l.reverse() self.name_backwards = ''.join(l) filename = 'pickle_temp' with open(filename, 'rb') as rf: while True: try: obj = pickle.load(rf) except EOFError: break else: print('{} ({})'.format(obj.name, obj.name_backwards))
运行效果
[root@ mnt]# python3 pickle_load_to_file.py pickle (elkcip) preserve (evreserp) last (tsal)
6、pickle序列化与反序列化会触发内置函数__getstate__与__setstate__的示例
#!/usr/bin/env python3 # encoding: utf-8 import pickle class State(object): def __init__(self, name): self.name = name def __repr__(self): # 命令行运行时,打印的对象信息格式化 return 'State({!r})'.format(self.__dict__) class MyClass(object): def __init__(self, name): print('MyClass __init__({})'.format(name)) self._set_name(name) def _set_name(self, name): self.name = name self.computed = name[::-1] def __repr__(self): return 'MyClass({!r}) (computed={!r})'.format( self.name, self.computed ) def __getstate__(self): state = State(self.name) print('__getstate__->{!r}'.format(state)) return state def __setstate__(self, state): print('__setstate__->{!r}'.format(state)) self._set_name(state.name) inst = MyClass('name here') print('之前的值', inst) # 序列化 dumped = pickle.dumps(inst) # 触发__getstate__函数 # 反序列化 reloaded = pickle.loads(dumped) # 触发__setstate__函数 print('之后的值', reloaded)
运行效果
[root@ mnt]# python3 pickle_state.py MyClass __init__(name here) 之前的值 MyClass('name here') (computed='ereh eman') __getstate__->State({'name': 'name here'}) __setstate__->State({'name': 'name here'}) 之后的值 MyClass('name here') (computed='ereh eman')
7、pickle序列化与反序列化树型结构的示例
结构图:
#!/usr/bin/env python3 # encoding: utf-8 import pickle class Node(object): def __init__(self, name): self.name = name self.connections = [] def add_edge(self, node): # 增加节点 self.connections.append(node) def __iter__(self): # 迭代对象的时候,触发 return iter(self.connections) def preorder_traversal(root, seen=None, parent=None): """递归遍历父子节点的关系""" if seen is None: seen = set() yield (parent, root) if root in seen: return seen.add(root) for node in root: recurse = preorder_traversal(node, seen, root) for parent, subnode in recurse: yield (parent, subnode) def show_edges(root): """打印出整棵树的父+子节点""" for parent, child in preorder_traversal(root): if not parent: continue print('{:>5} -> {:>2} ({})'.format(parent.name, child.name, id(child))) root = Node('root') a = Node('a') b = Node('b') c = Node('c') root.add_edge(a) root.add_edge(b) a.add_edge(b) b.add_edge(a) b.add_edge(c) a.add_edge(a) print('序列化前的数据:') show_edges(root) # 序列化 pickle_data = pickle.dumps(root) # 反序列化 unpickle_data = pickle.loads(pickle_data) print('反序列化后的数据') show_edges(unpickle_data)
运行效果
[root@python-mysql mnt]# python3 pickle_cycle.py 序列化前的数据: root -> a (139948184151096) a -> b (139948184151208) b -> a (139948184151096) b -> c (139948184152272) a -> a (139948184151096) root -> b (139948184151208) 反序列化后的数据 root -> a (139948183562952) a -> b (139948183563008) b -> a (139948183562952) b -> c (139948183563064) a -> a (139948183562952) root -> b (139948183563008)