pickle是什么
想把某个对象存储起来,可以以数据库的形式,但这种做法有些缺点:
- 存储后的数据可以被其它程序调用,违反面向对象封装性原则
- 数据库不理解对象,并且会强行使用自己的类型系统
pickle的特点是可以存储对象的同时,保持对象之间的关系。
简要用法
import pickle
with open(filename, 'wb') as f:
pickle.dump(content, f)
with open(filename, 'rb') as f:
content = pickle.load(f)
# 或者存到一个变量中
content = ['Hello', 'World', '!']
serialized = pickle.dumps(content) # res 是 bytes 类型的序列化之后的数据
pickle.loads(serialized) # 反序列化:还原
特性
如果对象的引用深度非常深,会报错,可以加下面一段解决
sys.setrecursionlimit(10000)
先进先出
import pickle
a = 'haha'
b = [1, 2, 3]
c = {3: 'ds', 1: '32'}
f1 = open('temp.pkl', 'wb')
pickle.dump(a, f1, True)
pickle.dump(b, f1, True)
pickle.dump(c, f1, True)
f1.close()
f2 = open('temp.pkl', 'rb')
print(pickle.load(f2))
print(pickle.load(f2))
print(pickle.load(f2))
f2.close()
输出:
haha
[1, 2, 3]
{3: 'ds', 1: '32'}
保持对象的引用关系1
import pickle
a = [1, 2, 3]
b = a
f1 = open('temp1.pkl', 'wb')
pickle.dump((a, b), f1)
f1.close()
f2 = open('temp1.pkl', 'rb')
c, d = pickle.load(f2)
c.append(4)
print(d)
输出:
[1, 2, 3, 4]
由此可见,完美保持了对象之间的引用关系
保持对象的引用关系2
import pickle
a = [1, 2, 3]
b = [4, 5, 6]
a.append(b)
b.append(a)
f = pickle.dumps((a, b))
c, d = pickle.loads(f)
print(c in d, d in c)
输出:
True True
分别pickle无法保持引用关系
分别pickle无法保持引用关系!(重要!)
import pickle
a = [1, 2, 3]
b = [4, 5, 6]
a.append(b)
b.append(a)
f = open('temp3.pkl', 'wb')
pickle.dump(a, f)
pickle.dump(b, f)
f.close()
f1 = open('temp3.pkl', 'rb')
c = pickle.load(f1)
d = pickle.load(f1)
f1.close()
c[2] is d
输出:
False
json
- 应用广泛,可以在不同语言、前后端之间传输数据。
- 但是只能序列化 dict
- 使用方法与 pickle 完全一致
import json
d = {'name': 'Tom', 'age': 20}
json_str = json.dumps(d,ensure_ascii=False)
d1 = json.loads(json_str)
或者存文件
d = {'name': 'Tom', 'age': 20}
# 存到 json 文件
with open('file.json', 'w') as f:
json_str = json.dump(d, f, ensure_ascii=False, indent=0)
# 不加 indent,所有都放到1行。加了以后更好看。
with open('file.json', 'r') as f:
d1 = json.load(f)
PickleSerializer
功能与 pickle 类似
准备你的模型
from sklearn import linear_model
lm=linear_model.LinearRegression()
x=np.random.rand(1000,1)
y=x+0.1*np.random.rand(1000,1)
lm.fit(x,y)
模型转为文本
from pyspark import PickleSerializer
ps=PickleSerializer()
model_str=ps.dumps(obj=lm)
# 是一个 byte 类型的数据,然后可以存到hive了
# 存hive略,要先用 str(model_str) 转为str,然后存hive
# 从hive读取时,用 eval() 转回 Byte 格式
文本转模型
from pyspark import PickleSerializer
ps=PickleSerializer()
model_load=ps.loads(model_str)
model_load.predict([[0.1]])
另外
这个可以序列化 iterator,不过还没试过
ps.dump_stream
ps.load_stream
MarshalSerializer:faster than PickleSerializer but supports fewer datatypes