一、json与pickle模块
json模块与pickle模块是用来给对象进行序列化的。
①__什么是序列化?
序列化指的是把内存里的数据类型转换成一种特定格式的内容,该格式的内容可以用于存储或传输给其他平台使用。
与之对应的是反序列化,顾名思义,就是把这种特定格式的内容反向转换成原来的数据类型。
- 内存中的数据类型 ----> 序列化 ----> 特定的格式(json格式或者pickle格式)
- 内存中的数据类型 <---- 反序列化 <---- 特定的格式(json格式或者pickle格式)
我们之前其实就使用过序列化与反序列化的思想:
{'aaa':111} ---> 序列化str({'aaa':111}) ---> "{'aaa':111}"
{'aaa':111} <--- 反序列化eval("{'aaa':111}") <--- "{'aaa':111}"
②__为什么要序列化?
序列化得到结果 ==> 特定的格式的内容有两种用途:
-
可用于存储 ==> 用于存档
-
传输给其他平台使用 ==> 跨平台数据交互
如果我们要在不同的编程语言之间传递对象,比如Python的列表传送到Java环境或JavaScript环境,是不能被识别出来的。而我们就必须把对象序列化为一种大家都支持的中间格式,然后再进行转换。
针对用途1的特定格式:可以是一种专用的格式 ==》==pickle==(只有python可以识别)
针对用途2的特定格式:应该是一种通用的、能够被所有语言识别的格式 ==》==json==
==json表示的对象就是标准的JavaScript语言的对象==,JSON和Python内置的数据类型对应如下:
| Json类型 | Python类型 |
|---|---|
| {} | dict |
| [] | list |
| =="==string=="== | str |
| 1234.56 | int或float |
| true/false | True/False |
| null | None |
③__如何序列化与反序列化?(import json)
-
序列化:json.dumps()
import json res = json.dumps(True) print(res, type(res)) # true <class 'str'> ret = json.dumps([1, 'a', False]) print(res, type(res)) # [1, "a", false] <class 'str'> -
反序列化:json.loads()
# 接上一代码块 l = json.loads(ret) print(l, type(l)) # [1, 'a', False] <class 'list'>
序列化后写入文件,与从文件读取json格式的字符串进行反序列化
序列化写入文件:
-
序列化的结果写入文件的复杂方法
import json json_res = json.dumps([1, 'aaa', True, False]) with open('test.json', mode='wt', encoding='utf-8') as f: f.write(json_res) -
将序列化的结果写入文件的简单方法:json.dump()
import json with open('test.json', mode='wt', encoding='utf-8') as f: json.dump([1, 'aaa', True, False], f)
test.json文件内容为:
[1, "aaa", true, false]
从文件读取json进行反序列化:
-
从文件读取json格式的字符串进行反序列化操作的复杂方法
import json with open('test.json', mode='rt', encoding='utf-8') as f: json_res = f.read() l = json.loads(json_res) print(l, type(l)) # [1, 'aaa', True, False] <class 'list'> -
从文件读取json格式的字符串进行反序列化操作的简单方法:json.load()
import json with open('test.json', mode='rt', encoding='utf-8') as f: l = json.load(f) print(l, type(l)) # [1, 'aaa', True, False] <class 'list'>
强调:
-
json格式兼容的是所有语言共同通用的数据类型,不能识别某一语言的所独有的类型
import json # python独有的集合类型,放进去识别不出来,会报错 json.dumps({1,2,3,4,5}) -
一定要搞清楚json格式,不要与python混淆,比如json的字符串格式只能是双引号。
import json json.loads('[1, "a", false]') -
在python解释器2.7与3.6之后都可以json.loads(bytes类型),但唯独3.5不可以。
import json json.loads(b'{"a":111}')
④__猴子补丁
属性在运行时的动态替换,叫做猴子补丁(Monkey Patch)。==猴子补丁的核心就是用自己的代码替换所用模块的源代码==。
如果我们的程序中已经基于json模块编写了大量代码了,发现有一个模块ujson比它性能更高,但用法一样。我们肯定不想把所有代码里的json.dumps或json.loads都换成ujson.dumps或者ujson.loads,这样做太麻烦了。或者是把import json改成import ujson as json,这样做的话需要每个文件都重新导入一下,也太麻烦了。
那我们可能会想到这么做,直接在程序的入口文件中加上:
import json
import ujson
json.dumps = ujson.dumps
json.loads = ujson.loads
我们可以将这个代码封装成一个功能函数:
# 在入口处打猴子补丁
import json
import ujson
def monkey_patch_json():
json.__name__ = 'ujson'
json.dumps = ujson.dumps
json.loads = ujson.loads
monkey_patch_json() # 在入口文件处运行
之所以在入口处加,是因为模块在导入一次后,后续的导入便直接引用第一次导入的成果。
其实这种场景也比较多,比如我们引用团队通用库里的一个模块,又想丰富模块的功能,除了继承之外也可以考虑用MonkeyPatch。采用猴子补丁之后,如果发现ujson不符合预期,那也可以快速撤掉补丁。
但要注意MonkeyPatch带了便利的同时也有搞乱源代码的风险
⑤__pickle模块
使用pickle进行序列化与反序列化的方法在==形式==上和json是一样的。
序列化后写入文件(注意pickle这里使用wb),与从文件读取==pickle格式的byte数据==进行反序列化的使用方法,在==形式==上也和json一样。
import pickle
pickle.dumps()
pickle.loads()
pickle.dump()
pickle.load()
==pickle序列化的结果是byte类型==
import pickle
res = pickle.dumps({1, 2, 3})
print(res, type(res))
# b'\x80\x04\x95\x0b\x00\x00\x00\x00\x00\x00\x00\x8f\x94(K\x01K\x02K\x03\x90.' <class 'bytes'>
s = pickle.loads(res)
print(s, type(s))
# {1, 2, 3} <class 'set'>
pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python。
并且此方法Python2与Python3彼此都不兼容,因此,只能用pickle保存那些不重要的数据,不能成功地反序列化也没关系。
⑥__了解知识
XML模块
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单。xml协议在各个语言里都是支持的,在json还没诞生的黑暗年代,大家只能选择用xml。
二、configparser模块
configparser 是用来读取配置文件(.ini)的模块。
配置文件test.ini文件的内容如下:中括号“[ ]”内包含的为section,section 下面为类似于key-value 的配置内容。
# 注释符号1
; 注释符号2
[section1]
k1 = v1
k2 : v2
user = BOSS
age = 18
is_admin = true
IQ = 0
[section2]
k3 = v3
使用configparser 首先需要初始化实例,并读取配置文件:
import configparser
config = configparser.ConfigParser()
config.read('test.ini')
-
获取sections
print(config.sections()) # ['section1', 'section2'] -
获取某一section下的所有options
print(config.options('section1')) # ['k1', 'k2', 'user', 'age', 'is_admin', 'iq'] -
获取某一section的items(所有配置项与对应信息)
print(config.items('section1')) # [('k1', 'v1'), ('k2', 'v2'), ('user', 'BOSS'), ('age', '18'), ('is_admin', 'true'), ('iq', '0')] -
获取指定的option对应值,默认都是str类型
res = config.get('section1', 'user') print(res, type(res)) # BOSS <class 'str'> res = config.getint('section1', 'age') # 获取并转换成int类型 print(res, type(res)) # 18 <class 'int'> res = config.getboolean('section1', 'is_admin') # 获取并转换成布尔类型 print(res, type(res)) # True <class 'bool'> res = config.getfloat('section1', 'iq') # 获取并转换成float类型 print(res, type(res)) # 0.0 <class 'float'>