python pickle 读写文件整理

 

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可以序列化什么类型的数据呢? 几乎所有数据类型

  1. 所有python支持的原生类型:布尔值,整数,浮点数,复数,字符串,字节,None。
  2. 由任何原生类型组成的列表,元组,字典和集合。
  3. 函数,类,类的实例

 

序列化方法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)

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值