序列化
-
json模块
可以在不同的系统见进行序列化/反序列化内置数据类型序列化和反序列化
序列化 json.dumps()
# 序列化 # sort_keys参数: 表示序列化时是否对dict的key进行排序(dict默认是无序的) # indent参数: 表示缩进的意思 # separators=(',',':') 去掉json字符串中:和,后的空白字符 >>> json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}) '{"a": "str", "c": true, "b": 11.1, "e": 10, "d": null, "g": [4, 5, 6], "f": [1, 2, 3]}'
反序列化 json.loads()
>>> json.loads('{"a":"str","c":true,"b":11.1,"e":10,"d":null,"g":[4,5,6],"f":[1,2,3]}') {'c': True, 'e': 10, 'a': 'str', 'g': [4, 5, 6], 'd': None, 'f': [1, 2, 3], 'b': 11.1}
dump()和load()函数示例:
# 序列化到文件中 >>> with open('test.json', 'w') as fp: ... json.dump({'a':'str中国', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}, fp, indent=4) # 反序列化文件中的内容 >>> with open('test.json', 'r') as fp: ... json.load(fp) {'e': 10, 'g': [4, 5, 6], 'b': 11.1, 'c': True, 'd': None, 'a': 'str中国', 'f': [1, 2, 3]}
自定义数据类型的序列化/反序列化
实现方式:
- 转换函数实现
- 继承JSONEncoder、JSONDecoder实现
import json class Student: def __init__(self, name, age): self.name = name self.age = age def student2dict(obj): """对象 --> dict""" """必须返回序列化结果""" d = {} d['__class__'] = obj.__class__.__name__ # 踩坑:obj.__class__ 造成返回不是序列化结果,抛错 d['__module__'] = obj.__module__ d.update(obj.__dict__) return d class MyJSONEncoder(json.JSONEncoder): def default(self, obj): d = {} d['__class__'] = obj.__class__.__name__ # 踩坑:obj.__class__ 造成返回不是序列化结果,抛错 d['__module__'] = obj.__module__ d.update(obj.__dict__) return d def dict2student(dic): """dict --> 对象""" """传入的dict""" if '__class__' in dic: class_name = dic.pop('__class__') module_name = dic.pop('__module__') module = __import__(module_name) class_ = getattr(module, class_name) args = dict( (k, v) for k, v in dic.items()) ins = class_(**args) # 解包成位置参数 else: ins = dic return ins class MyJSONDecoder(json.JSONDecoder): def __init__(self): super().__init__(object_hook=dict2student) def dict2student(self, dic): """dict --> 对象""" """传入的dict""" if '__class__' in dic: class_name = dic.pop('__class__') module_name = dic.pop('__module__') module = __import__(module_name) class_ = getattr(module, class_name) args = dict((k, v) for k, v in dic.items()) ins = class_(**args) # 解包成位置参数 else: ins = dic return ins stu = Student('Tom', 25) # default将对象转换为可序列为json对象,然后调用dumps() dump = json.dumps(stu,default=student2dict) # {"__class__": "Student", "__module__": "__main__", "name": "Tom", "age": 25} dump1 = MyJSONEncoder().encode(stu) # MyJSONEncoder.encode(stu) 这样调用会报错,因为encode(self, o)是一个实例方法,类外不能被类调用 dump2 = MyJSONEncoder(separators=(',', ':')).encode(stu) dump3 = json.dumps(stu, cls=MyJSONEncoder) # 类似于dump调用 dump4 = json.dumps(stu, cls=MyJSONEncoder, separators=(',', ':')) # loads()方法先转换出一个dict对象,然后object_hook函数负责将dict转换为Student实例 load = json.loads(dump,object_hook=dict2student) # <__main__.Student object at 0x0000014F920EC278> load1 = MyJSONDecoder().decode(dump) load2 = json.loads(dump, cls=MyJSONDecoder)
-
pickle模块
仅仅用于python内部数据序列化/反序列化.
内置数据类型序列化/反序列化:
import pickle var_a = {'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)} # 序列化为字节 var_b = pickle.dumps(var_a) var_c = pickle.loads(var_b) # 必须以二进制打开 with open('pickle.txt','wb') as fp: pickle.dump(var_a,fp) with open('pickle.txt','rb') as fp: var_d = pickle.load(fp)
自定义数据类型的序列化/反序列化:
pickle不需要编写额外的处理函数或类,可以直接对自定义数据类型进行序列化/反序列化
注意:dump和load需要以二进制打开文件 -
shelve模块
内部封装的是pickle模块,只有一个open()函数,这个函数用于打开指定的文件(一个持久的字典),然后返回一个shelf对象.
shelf类似于dict,可以进行在线操作对象.with shelve.open('student') as fp: fp['name'] = 'Tom' fp['age'] = 25 with shelve.open('student') as fp: for k,v in fp.items(): print(k,v)
比较
JSON是文本形式的存储,Pickle则是二进制形式(至少常用二进制)
JSON是人可读的,Pickle不可读(二进制形式及加密)
JSON广泛应用于除Python外的其他领域,Pickle是Python独有的。
JSON只能dump一些python的内置对象,Pickle可以存储几乎所有对象。
偏向应用特别是web应用方面,可以常用JSON格式. 偏向算法方面,尤其是机器学习,则应该使用cPickle.