pickle提供了一个简单的持久化功能。可以将对象以文件的形式存放在磁盘上。
Python 中Pickle库的使用详解 https://www.jb51.net/article/135407.htm
pickle协议和JSON(JavaScript Object Notation)的区别 :
1. JSON是一种文本序列化格式(它输出unicode文本,虽然大部分时间它被编码utf-8
),而pickle是二进制序列化格式;
2. JSON是人类可读的,而pickle则不是;
3. JSON是可互操作的,并且在Python生态系统之外广泛使用,而pickle是特定于Python的;
pickle可以序列化什么类型的数据呢? 几乎所有数据类型
- 所有python支持的原生类型:布尔值,整数,浮点数,复数,字符串,字节,None。
- 由任何原生类型组成的列表,元组,字典和集合。
- 函数,类,类的实例
序列化方法pickle.dump(obj,file) 和 反序列化方法pickle.load(file) 注意必须采用二进制形式打开文件
# 序列化: python 所有数据结构, 注意必须采用二进制形式打开文件
import pickle
with open('test.txt', 'wb') as file:
pickle.dump(object, file)
# 反序列化: 注意采用二进制形式打开文件
import pickle
with open('test.txt', 'rb') as file:
model = pickle.load(file)
with open('test_pickle.dat','wb')as dest: # 以二进制模式打开文件
datas = {'name':'张三','age':25,'high':175} #
pickle.dump(datas,dest) # 将文件 以utf-8的格式编码成二进制并写入文件
# 能读取到read binary file: [b'\x80\x03}q\x00(X\x04\x0。。。。
with open('test_pickle.dat','rb')as src: # 定义了 以二进制的方式读取文件, src可以理解为一个数据流管道
lines=src.readlines() # 从管道里取出数据
print("read binary file:",lines) # 读取的是 用utf-8编码成二进制的内容 如:b'\x80\x03(16进制表示形式,等价于二进制) 之所以不是01的形式 是为了在ide环境中让我们相对直观的观察,
with open('test_pickle.dat','r+',encoding='GBK')as src:
lines=src.readlines()
print("read binary file:",lines)
# 报错'gbk' codec can't decode byte 0x80 in position 0: illegal multibyte sequence
'''
原因: 在用open()打开文件时open()默认采用文本模式 Pickle 写入的file都是二进制模式,打开模式一定要加'b', 否则会报错
'''
pickle 用rb读取的方式 读取的不应该是二进制文件吗??
# 如果文件存在就读取,如果不存在就创建并写入
if os.path.exists(file_path):
actions = pickle.load(open(file_path, 'rb'))
else:
df=pd.DataFrame({}) # 数据
pickle.dump(df, open(file_path, 'wb'))
return df
关于pickle模块追加写入读取的问题
pickle模块对数据进行序列化存储,但是在使用过程中发现按照教程上的追加写入后,读取出来的总是第一个对象。查找资料后发现,Pickle 每次序列化生成的字符串有独立头尾,pickle.load() 只会按顺序读取一个完整的结果,所以只需要在 load 一次之后再 load 一次,就能读到第二次序列化的 对象。如果不知道文件里有多少 pickle 对象,可以在 while 循环中反复 load 文件对象,直到抛出异常为止。
with open('test','ab') as f:
pickle.dump('123',f)
pickle.dump('456',f)
f.close()
with open('test','ab') as f:
pickle.dump('789',f)
f.close()
with open('test','rb') as f:
while True:
try:
aa=pickle.load(f)
print(aa)
except EOFError:
break
运行结果:
编码问题:
1. 可以看到 本地mac在使用open()方法时默认的字符集是utf-8。
本地系统 打开文本文件的编码方式是utf-8,python 将二进制数据 转化为文本/对象 的编码方式也是utf-8
'''
locale.getpreferredencoding() 重要参数,默认为打开本地操作系统读取的文本文件的编码方式,因操作系统而异,除非指定
sys.stdout/stdin/stderr 标准输出/输入/错误输出 PYTHONIOENCODING 变量指定
sys.getdefaultencoding() python将binary data转换为str的默认编码方法
sys.getfilesystemencoding() Python编码解码文件名,调用操作系统文件API
'''
import sys,locale
print(locale.getpreferredencoding()) # utf-8
print(sys.getdefaultencoding()) # utf-8
with open('test1.txt','w+', encoding='gbk') as file:
file.write("abc中国abcdeffg")
# 1. 手动点击打开文本 采用的是 locale.getpreferredencoding() 编码方式
#比如点击打开本地test1.txt文件,如果该文件时以gbk编码方式写入的话,
#点击打开的时候采用的默认打开文件的编码方式(utf-8)就会报test1.txt is not utf-8 encode
# 2.open 打开 采用的是 sys.getdefaultencoding()编码方式(python将binary data转换为str的默认编码方法)
with open('test1.txt','r+')as file: # 定义了 以二进制的方式读取文件, file 可以理解为一个数据流管道, 采用默认的解码方式utf8
print(file.readline())
2. pickl 读取/写入文件的详细流程:
import pickle
'''
以二进制方式读取/写入文件
'''
with open('test_pickle.dat','wb')as dest: # 以二进制模式打开文件
datas = {'name':'张三','age':25,'high':175} #
pickle.dump(datas,dest) # 将文件 以utf-8的格式编码成二进制并写入文件
with open('test_pickle.dat','rb')as src: # 定义了 以二进制的方式读取文件, src可以理解为一个数据流管道
lines=src.readlines() # 从管道里取出数据
print("read binary file:",lines) # 读取的是 用utf-8编码成二进制的内容 如:b'\x80\x03(16进制表示形式,等价于二进制) 之所以不是01的形式 是为了在ide环境中让我们相对直观的观察,
print("--"*50)
with open('test_pickle.dat','rb')as file: # 以二进制的方式读取文件, 此时 不能再open中加encoding 因为读出的是二进制不需要解码,加了会报错
n=pickle.load(file) # 先读取到文件的二进制内容,然后用utf-8解码 得到 可读的内容
print(n)
print("--"*50)
#如果文本以其他方式编码的,读取时可以指定解码方式如下面的gbk:
with open('test_pickle.dat','rb')as file: # 定义了 以二进制的方式读取文件, file 可以理解为一个数据流管道
n=pickle.load(file) # 具体执行:先读取到文件的二进制内容,然后用utf-8解码 得到 可读的内容
print(n)