pickle — 对象序列化
优质
小牛编辑
136浏览
2023-12-01
字符串数据编码和解码
# pickle_string.py
import pickle
import pprint
data = [{'a': 'A', 'b': 2, 'c': 3.0}]
print('DATA:', end=' ')
pprint.pprint(data)
data_string = pickle.dumps(data)
print('PICKLE: {!r}'.format(data_string))
# pickle_unpickle.py
import pickle
import pprint
data1 = [{'a': 'A', 'b': 2, 'c': 3.0}]
print('BEFORE: ', end=' ')
pprint.pprint(data1)
data1_string = pickle.dumps(data1)
data2 = pickle.loads(data1_string)
print('AFTER : ', end=' ')
pprint.pprint(data2)
print('SAME? :', (data1 is data2))
print('EQUAL?:', (data1 == data2))
处理流
# pickle_stream.py
import io
import pickle
import pprint
class SimpleObject:
def __init__(self, name):
self.name = name
self.name_backwards = name[::-1]
return
data = []
data.append(SimpleObject('pickle'))
data.append(SimpleObject('preserve'))
data.append(SimpleObject('last'))
# Simulate a file.
out_s = io.BytesIO()
# Write to the stream
for o in data:
print('WRITING : {} ({})'.format(o.name, o.name_backwards))
pickle.dump(o, out_s)
out_s.flush()
# Set up a read-able stream
in_s = io.BytesIO(out_s.getvalue())
# Read the data
while True:
try:
o = pickle.load(in_s)
except EOFError:
break
else:
print('READ : {} ({})'.format(
o.name, o.name_backwards))
重建对象问题
# pickle_dump_to_file_1.py
import pickle
import sys
class SimpleObject:
def __init__(self, name):
self.name = name
l = list(name)
l.reverse()
self.name_backwards = ''.join(l)
if __name__ == '__main__':
data = []
data.append(SimpleObject('pickle'))
data.append(SimpleObject('preserve'))
data.append(SimpleObject('last'))
filename = sys.argv[1]
with open(filename, 'wb') as out_s:
for o in data:
print('WRITING: {} ({})'.format(
o.name, o.name_backwards))
pickle.dump(o, out_s)
# pickle_load_from_file_1.py
import pickle
import pprint
import sys
filename = sys.argv[1]
with open(filename, 'rb') as in_s:
while True:
try:
o = pickle.load(in_s)
except EOFError:
break
else:
print('READ: {} ({})'.format(
o.name, o.name_backwards))
Unpicklable对象
# pickle_state.py
import pickle
class State:
def __init__(self, name):
self.name = name
def __repr__(self):
return 'State({!r})'.format(self.__dict__)
class MyClass:
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('Before:', inst)
dumped = pickle.dumps(inst)
reloaded = pickle.loads(dumped)
print('After:', reloaded)
循环引用
# pickle_cycle.py
import pickle
class Node:
"""A simple digraph
"""
def __init__(self, name):
self.name = name
self.connections = []
def add_edge(self, node):
"Create an edge between this node and the other."
self.connections.append(node)
def __iter__(self):
return iter(self.connections)
def preorder_traversal(root, seen=None, parent=None):
"""Generator function to yield the edges in a graph.
"""
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):
"Print all the edges in the graph."
for parent, child in preorder_traversal(root):
if not parent:
continue
print('{:>5} -> {:>2} ({})'.format(
parent.name, child.name, id(child)))
# Set up the nodes.
root = Node('root')
a = Node('a')
b = Node('b')
c = Node('c')
# Add edges between them.
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('ORIGINAL GRAPH:')
show_edges(root)
# Pickle and unpickle the graph to create
# a new set of nodes.
dumped = pickle.dumps(root)
reloaded = pickle.loads(dumped)
print('\nRELOADED GRAPH:')
show_edges(reloaded)