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)
pickle_string.py

运行效果

[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))
pickle_unpickle.py

运行效果

[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))
pickle_stream.py

运行效果

[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)  # 序列化到文件中
pickle_dump_to_file.py

运行效果

[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))
pickle_load_to_file.py

运行效果

[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)
pickle_state.py

 运行效果

[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)
pickle_cycle.py

 运行效果

[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)
posted @ 2020-01-12 14:56  小粉优化大师  阅读(464)  评论(0编辑  收藏  举报