Python序列化

本文介绍了Python的序列化概念,包括持久化、序列化的重要性。详细讨论了json模块,包括接口、数据类型对应关系以及注意事项。接着提到了pickle模块,最后介绍了shelve模块,它是一个持久化的key-value存储,结合了pickle的序列化协议,提供更便捷的操作方式。
摘要由CSDN通过智能技术生成

持久化

所谓持久化就是把内存中的数据保存在外存(包括数据库)中,达到长期保存的目的。

序列化

序列化就是讲数据转换为可以通过网络传输或者可以存储到本地磁盘的数据格式(例如xml、json、字符串等)
Python常用的序列化模块有json、pickle、shelve。

比较

模块名称描述提供的api
json用于实现Python数据类型与通用(json)字符串之间的转换dumps()、dump()、loads()、load()不能转换自定义类型。明文保存,保密性差
pickle用于实现Python数据类型与Python特定二进制格式之间的转换dumps()、dump()、loads()、load()不能用于Python之外
shelve专门用于将Python数据类型的数据持久化到磁盘,shelve是一个类似dict的对象,操作十分便捷open()只能用在Python中

json

接口

json模块提供了以下两个方法来进行序列化和反序列化操作:

# 序列化:将Python对象转换成json字符串
dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

# 反序列化:将json字符串转换成Python对象
loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

除此之外,json模块还提供了两个额外的方法允许我们直接将序列化后得到的json数据保存到文件中,以及直接读取文件中的json数据进行反序列化操作:

# 序列化:将Python对象转换成json字符串并存储到文件中
dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

# 反序列化:读取指定文件中的json字符串并转换成Python对象
load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

JSON与Python之间数据类型对应关系

Python转JSON

PythonJSON
dictObject
list, tuplearray
strstring
int, float, int- & float-derived Enumsnumbers
Truetrue
Falsefalse
Nonenull

JSON转Python

JSONPython
objectdict
arraylist
stringstr
number(int)int
number(real)float
trueTrue
falseFalse
nullNone

注意

  • Python dict中的非字符串key被转换成JSON字符串时都会被转换为小写字符串;
  • 自定义类型不能直接转换,比较麻烦。参考
  • sort_keys参数: 表示序列化时是否对dict的key进行排序(dict默认是无序的)
  • indent参数: 表示缩进的意思,它可以使得数据存储的格式变得更加优雅、可读性更强;。参考

pickle

json和pickle都不能追加数据。

pickle模块提供的几个序列化/反序列化的函数与json模块基本一致:

# 将指定的Python对象通过pickle序列化作为bytes对象返回,而不是将其写入文件
dumps(obj, protocol=None, *, fix_imports=True)

# 将通过pickle序列化后得到的字节对象进行反序列化,转换为Python对象并返回
loads(bytes_object, *, fix_imports=True, encoding="ASCII", errors="strict")

# 将指定的Python对象通过pickle序列化后写入打开的文件对象中,等价于`Pickler(file, protocol).dump(obj)`
dump(obj, file, protocol=None, *, fix_imports=True)

# 从打开的文件对象中读取pickled对象表现形式并返回通过pickle反序列化后得到的Python对象
load(file, *, fix_imports=True, encoding="ASCII", errors="strict")

pickle编码协议参考

shelve

shelve类似key-value数据库,内部是通过pickle协议来实现数据序列化。shelve只有一个open()函数,返回一个shelf对象。shelf是一种持久的、类似字典的对象。它与“dbm”的不同之处在于,其values值可以是任意基本Python对象–pickle模块可以处理的任何数据。keys是普通的字符串。

open(filename, flag='c', protocol=None, writeback=False)

flag 参数表示打开数据存储文件的格式,可取值与dbm.open()函数一致:

描述
‘r’以只读模式打开一个已经存在的数据存储文件
‘w’以读写模式打开一个已经存在的数据存储文件
‘c’以读写模式打开一个数据存储文件,如果不存在则创建
‘n’总是创建一个新的、空数据存储文件,并以读写模式打开

protocol 参数表示序列化数据所使用的协议版本,默认是pickle v3;
writeback 参数表示是否开启回写功能。(下面会说)

我们可以把shelf对象当dict来使用–存储、更改、查询某个key对应的数据,当操作完成之后,调用shelf对象的close()函数即可。当然,也可以使用上下文管理器(with语句),避免每次都要手动调用close()方法。

shelve模块可以看做是pickle模块的升级版,因为shelve使用的就是pickle的序列化协议,但是shelve比pickle提供的操作方式更加简单、方便。shelve模块相对于其它两个模块在将Python数据持久化到本地磁盘时有一个很明显的优点就是,它允许我们可以像操作dict一样操作被序列化的数据,而不必一次性的保存或读取所有数据。

源码

# -*- coding: utf-8 -*-  
'''
@finish time:2017-09-30
@author;fengjiexyb
序列化的模块比较
'''
import json
import pickle
import shelve

def shelveSerializable():
    '''这种方式在python2.7中会有异常:AttributeError: DbfilenameShelf instance has no attribute '__exit__'
    # 保存数据到student文件
    with shelve.open('student') as db:
        db['name'] = 'Tom'
        db['age'] = 19
        db['hobby'] = ['篮球', '看电影', '弹吉他']
        db['other_info'] = {'sno': 1, 'addr': 'xxxx'}

    # 读取数据
    with shelve.open('student') as db:
        for key, value in db.items():
            print(key, ': ', value)
    '''
    s = shelve.open("test_shelve")
    s["name"] = "DaLian"
    s["neusoft"] = "HHH"
    s.close()

    f = shelve.open("test_shelve")#如果上面没有关闭,但是文件存在,就会读取以前的文件,而不是上面的新文件。
    print(f.get("name"))
    print(f.get("neusoft"))

    f["neusoft"] = "sss" #可以修改
    f["soft"] = [1,2]  #可以添加
    print(f.get("neusoft"))
    print(f.get("soft"))
    f["soft"].append(3) #但是追加,还是会显示追加前的数据
    print(f.get("soft"))
    f.writeback = True #设置回写,也可以在打开文件时设置
    f["soft"].append(4) #现在就可以追加了
    print(f.get("soft"))

'''pickle序列化'''
def pickleSerializable():
    #序列化
    li = [1, 2, 3, 4, 5]
    pw = open('pickleSerializable', 'wb')
    pw.write(pickle.dumps(li))
    pw.close()

    #反序列化
    li = json.load(open("pickleSerializable", "r"))
    print(li, type(li))

'''json序列化'''
def jsonSerializable():
    dic = {'k1': 'v1'}
    print(dic, type(dic))
    # json.dumps 把python的基本数据类型转换成字符串形式
    result = json.dumps(dic)
    print(dic, type(result))

    # 反序列化
    s1 = '{"k1":123}'
    # json.loads 把字符串形式转换成其他基本数据类型
    # 注意: 反序列化时,中间字符串一定用""表示,原因:跨语言操作时,其他语言是用""表示字符串
    dic1 = json.loads(s1)
    print(dic1, type(dic1))

    # 序列化并把内容写进文本
    # 也可以写成pickle例子的形式
    li = [1, 2, 3, 4, 5]
    json.dump(li, open("test", "w"))

    # 从文本读出字符串并进行反序列化,但文件中的内容只能有一个基本数据
    li = json.load(open("test", "r"))
    print(li, type(li))

def main():
    shelveSerializable()

if __name__ == "__main__":
    main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值