json 模块
json简介
1、json格式是什么
# 把python中的字典,列表..数据类型转成json格式字符串
# 下面格式是标准的json格式字符串
{"name":"xio","age":18,"handsome":true,"xx":null}
2、json格式有什么用?
# 存取数据(格式标准),一个程序写入,另一个程序读取(这两个程序可以是不同的语言)
# 后端给前端的数据是json格式字符串
3、python中如何使用json
#序列化:把某个语言的变量转成json格式字符串
#反序列化:把json格式字符串转成某个语言的变量
# 补充:java中,出于性能的考虑,有很多包来完成序列化和反序列化:谷歌的gson 阿里开源fastjson
dumps
import json # 导入json模块,内置模块
# 序列化
# 定义一个字典
dic = {'name': 'xio', 'age': 18, 'handsome': True, 'xxx': None}
# 把字典转成json格式字符串
dic_str=json.dumps(dic)
print(dic_str) # {"name": "xio", "age": 18, "handsome": true, "xxx": null}
print(type(dic_str)) # <class 'str'>
loads
import json
# 反序列化
s='''
{"name": "xio", "age": 18, "handsome": true, "xxx": null}
'''
# 把json格式字符串反序列化成字典
s_dic=json.loads(s)
print(s_dic) # {'name': 'xio', 'age': 18, 'handsome': True, 'xxx': None}
print(type(s_dic)) # <class 'dict'>
# json模块可以序列化:字典,列表,布尔
# 稍微复杂点的字典+列表格式+布尔格式
dic = {'movieIds': [111, 222, 333, 444],
'stids': [{'movieId': 11, 'stid': 1}, {'movieId': 22, 'stid': 2}, {'movieId': 33, 'stid': 3}]}
res = json.dumps(dic)
print(res)
# {"movieIds": [111, 222, 333, 444], "stids": [{"movieId": 11, "stid": 1}, {"movieId": 22, "stid": 2}, {"movieId": 33, "stid": 3}]}
dump、load 文件应用
import json
# 序列化和反序列化放到文件中
# 土办法
dic = {'name': 'xio', 'age': 18, 'handsome': True, 'xxx': None}
dic_str = json.dumps(dic)
print(dic_str)
with open('a.json', 'wt', encoding='utf-8') as f:
f.write(dic_str)
# 序列化的简化写法
dic = {'name': 'xio', 'age': 18, 'handsome': True, 'xxx': None}
with open('a.json', 'wt', encoding='utf-8') as f:
json.dump(dic, f)
# 反序列化的简化写法
with open('a.json', 'rt', encoding='utf-8') as f:
dic = json.load(f)
print(dic)
print(type(dic))
补充:ensure_ascii=False
import json
dic = {'name': '小蜗', 'age': 18, 'handsome': True, 'xxx': None}
print(json.dumps(dic,ensure_ascii=False))
# {"name": "小蜗", "age": 18, "handsome": true, "xxx": null}
print(json.dumps(dic))
# {"name": "\u5c0f\u8717", "age": 18, "handsome": true, "xxx": null}
pickle 模块
pickle 序列化与反序列化
import pickle # 内置模块
# pickle序列化
dic={'name':'xio','age':18}
res=pickle.dumps(dic)
print(res)
#b'\x80\x04\x95\x1a\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x04name\x94\x8c\x03xio\x94\x8c\x03age\x94K\x12u.'
# pickle的反序列化
b = b'\x80\x04\x95\x1a\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x04name\x94\x8c\x03xio\x94\x8c\x03age\x94K\x12u.'
res = pickle.loads(b)
print(res) # {'name': 'xio', 'age': 18}
print(type(res)) # <class 'dict'>
文件+序列化和反序列化
import pickle
# 文件+序列化和反序列化
dic = {'name': 'xio', 'age': 18}
with open('a.pkl', 'wb') as f:
pickle.dump(dic, f)
with open('a.pkl', 'rb') as f:
res = pickle.load(f)
print(res)
比较pickle和json
'''
json:通用格式,任何语言都有,都可以解析,但是数据类型有限
pickle:只是python使用,转成b格式,其它语言识别不了,任意的数据类型都可以
'''
import json
import pickle
dic = {'a': input}
res = json.dumps(dic) # 报错
res1 = pickle.dumps(dic)
# b'\x80\x04\x95\x1d\x00\x00\x00\x00\x00\x00\x00}\x94\x8c\x01a\x94\x8c\x08builtins\x94\x8c\x05input\x94\x93\x94s.'
print(res)
dic_2 = pickle.loads(res1)
dic_2['a']() # 相当于调用了input功能
猴子补丁
# 一.什么是猴子补丁?
属性在运行时的动态替换,叫做猴子补丁(Monkey Patch)。
猴子补丁的核心就是用自己的代码替换所用模块的源代码,详细地如下
1,这个词原来为Guerrilla Patch,杂牌军、游击队,说明这部分不是原装的,在英文里guerilla发音和gorllia(猩猩)相似,再后来就写了monkey(猴子)。
2,还有一种解释是说由于这种方式将原来的代码弄乱了(messing with it),在英文里叫monkeying about(顽皮的),所以叫做Monkey Patch。
# 二. 猴子补丁的功能(一切皆对象)
1.拥有在模块运行时替换的功能, 例如: 一个函数对象赋值给另外一个函数对象(把函数原本的执行的功能给替换了)
class Monkey:
def hello(self):
print('hello')
def world(self):
print('world')
def other_func():
print("from other_func")
monkey = Monkey()
monkey.hello = monkey.world
monkey.hello()
monkey.world = other_func
monkey.world()
# 三.monkey patch的应用场景
如果我们的程序中已经基于json模块编写了大量代码了,发现有一个模块ujson比它性能更高,
但用法一样,我们肯定不会想所有的代码都换成ujson.dumps或者ujson.loads,那我们可能
会想到这么做
import ujson as json,但是这么做的需要每个文件都重新导入一下,维护成本依然很高
此时我们就可以用到猴子补丁了
只需要在入口处加上
, 只需要在入口加上:
import json
import ujson
def monkey_patch_json():
json.__name__ = 'ujson'
json.dumps = ujson.dumps
json.loads = ujson.loads
monkey_patch_json() # 之所以在入口处加,是因为模块在导入一次后,后续的导入便直接引用第一次的成果
#其实这种场景也比较多, 比如我们引用团队通用库里的一个模块, 又想丰富模块的功能, 除了继承之外也可以考虑用Monkey
Patch.采用猴子补丁之后,如果发现ujson不符合预期,那也可以快速撤掉补丁。个人感觉Monkey
Patch带了便利的同时也有搞乱源代码的风险!