本节内容:
1、什么是序列化
2、pickle(重点)
3、shelve 类似小型数据库
4、json(重点)
5、configparser模块
一、什么是序列化
在我们存储数据或者⽹络传输数据的时候. 需要对我们的对象进⾏处理.
把对象处理成⽅便存储和传输的数据格式. 这个过程叫序列化.
不同的序列化, 结果也不同. 但是⽬的是⼀样的. 都是为了存储和传输.
1、在python中存在三种序列化的⽅案
1. pickle. 可以将我们python中的任意数据类型转化成bytes并写入到⽂件中.
同样也可以把⽂件中写好的bytes转换回我们python的数据. 这个过程被称为反序列化
2. shelve. 简单另类的⼀种序列化的⽅案. 有点⼉类似后⾯我们学到的redis.
可以作为⼀种⼩型的数据库来使⽤
3. json. 将python中常⻅的字典, 列表转化成字符串.
是⽬前前后端数据交互使⽤频率最⾼的⼀种数据格式.
二、pickle(重点)
pickle⽤起来很简单. 说⽩了.
就是把我们的python对象写入到⽂件中的⼀种解决⽅案.
但是写入到⽂件的是bytes. 所以这东⻄不是给⼈看的. 是给机器看的.
序列化 把对象打散成二进制字节 bytes
1、 pickle 把一个对象转化成bytes写入到文件
pickle.dumps() 把对象转换成bytes
pickle.loads() 把bytes转化成对象
pickle.dump() 把对象转换成bytes. 写入到文件
pickle.load() 把文件中的bytes读取. 转化成对象
2、dumps和loads只是序列化和反序列化功能,
pickle中的dumps可以序列化⼀个对象. loads可以反序列化⼀个对象.
注意:没有写入文件和读取文件的功能
fe:
import pickle
class Cat:
def __init__(self, name, color):
self.name = name
self.color =color
def chi(self):
print("%s猫可以吃鱼" % self.name)
c = Cat("小白", "红色")
bs = pickle.dumps(c) # dumps序列化对象,把一个对象转化成 bytes类型,进行传输
print(bs)
s = pickle.loads(bs) # loads() 将字节还原对象, 对象还是那个对象,还可以执行吃鱼,但是创建猫的类不能没有,这个就好比是图纸,没有了无法复原
print(s)
print(s.name)
# 区别dump和load
c2 = Cat("小白2", "红色1")
pickle.dump(c, open("猫.db", mode = "wb")) # 把对象以二进制类型,写入到文件中
pickle.dump(c2, open("猫.db", mode = "ab")) # 重新打开写入用mode = "ab"
cc = pickle.load(open("猫.db", mode = "rb")) # 从文件中读取到对象
cc.chi()
print(cc.name) # 小白猫
se = pickle.load(open("猫.db", mode = "rb")) # 再拿一次就是下一个对象了
pirnt(se.name) # 小白2
3、dump和load((反)序列化 + 写读文件)的功能
这⾥记住, 不能⼀⾏⼀⾏的读. 那真的要写入或者读取多个内容怎么办?
很简单. 装list⾥. 然后读取和写入都⽤list
fe: 写入及读取多个对象
import pickle
class Cat:
def __init__(self, name, age):
self.name = name
self.age = age
def catchMouse(self):
print(self.name, "抓⽼⿏")
lst = [Cat("jerry", 19), Cat("tommy", 20), Cat("alpha", 21)]
# f = open("cat", mode="wb")
# for el in lst:
# pickle.dump(el, f) # 写⼊到⽂件中
# f.close()
f = open("cat", mode="rb")
for i in range(len(lst)):
cc = pickle.load(f) # 从⽂件中读取对象
cc.catchMouse()
f.close()
fe: pickle写注册登录的示例
class User:
def __init__(self, username, password):
self.username = username
self.password = password
class Admin:
def regist(self):
user = input("请输入用户名:")
pwd = input("请输入密码:")
u = User(user, pwd)
f = open("账户信息.txt", mode = "ab")
pickle.dump(u, f) # 前面是内容,后面是内容
print("注册成功!!!")
def login(self):
user = input("请输入用户名:")
pwd = input("请输入密码:")
f = open("账户信息.txt", mode = "rb")
while 1:
try: # 不知道文件中有多少个对象,所以要使用try,execpt来接收没有对象的错误
u = pickle.load(f) # 循环一次,拿到下一个对象, 跟__next__一样,只能向前,但是可以用seek(0),用光标调顺序
if u.name == user and u.password == pwd:
print("登录成功!!!")
break
except Exception as e:
print("登录失败!!")
break
a = Admin()
# a.regist()
# a.regist()
# a.regist()
# a.regist()
a.login()
三、shelve小型数据库(持久化操作)
shelve提供python的持久化操作. 什么叫持久化操作呢?
说⽩话,就是把数据写到硬盘上.
redis, mongodb, dict类似
在操作shelve的时候非常的像操作⼀个字典,
直接用字典的功能操作shelve
注意:
writeback = True 这样才能实现回写更新
1、基本操作
fe1: 写入和读取
import shelve
d = shelve.open("文件") # 文件类型的字典, 写文件名就行了,后面会默认加上.db
d["疏影"] = "暗香"
d.close()
d = shelve.open("文件")
print(d["疏影"]) # 查看
d.close()
有坑!!!
fe2: 修改字典里面嵌套的字典,必须用writeback = True,才能回写修改成功
import shelve
# 如果是字典里面嵌套字典,那么要修改里面的内容的时候,就要加上writeback = True,回写更新
d = shelve.open("文件")
d["大明"] = {"名字": "朱元璋", "职业": "当皇帝", "儿子": {"名字": "朱棣", "职业": "造反"}} # 写入嵌套的字典
d.close()
d = shelve.open("文件")
d["大明"]["儿子"]["职业"] = "勤王" # 并没有在文件修改,只是在内存中改了,没有更新进文件
d.close()
d = shelve.open("文件")
for k, v in d.items():
print(k, v)
d = shelve.open("文件", writeback = True) # 必须写了writeback = True,才会回写更新
d["大明"]["儿子"]["职业"] = "勤王" # 可以对文件进行回写更新了
d.close()
d = shelve.open("文件")
for k, v in d.items():
print(k, v)
四、json(重点掌握)
终于到json了. json是我们前后端交互的枢纽. 相当于编程界的普通话.
⼤家沟通都⽤json. 为什么这样呢? 因为json的语法格式可以完美的表⽰出⼀个对象.
那什么是json: json全称javascript object notation.
翻译过来叫js对象简谱. 很复杂是吧? 来上⼀段我们认识的代码:
1、字典转json字符串(用dumps),json字符串转字典(用loads)
s = json.dumps(d, ensure_ascii = False) # 默认用ascii码解析,所以要改,不要用ASCII解析中文
import json
# python中直接将字典或列表转换成json
d = {"朝代": "大明", "高祖": "朱元璋", "永乐大帝": "朱棣"}
s = json.dumps(d, ensure_ascii = False) # 默认用ascii码解析,所以要改,不要用ASCII解析中文
print(s)
print(type(s)) # <class 'str'>
# 把json字符串转换成字典
s = '{"朝代": "大明", "高祖": "朱元璋", "永乐大帝": "朱棣"}'
d = json.loads(s) # 把json转换成字典
print(d)
print(type(d)) # <class 'dict'>
2、json写入和读取文件
1.转换成json,并写入文件
2.读取json,转换成字典
fe: 用json写入及读取文件
# 转换成json,并写入文件
dic = {"朝代": "大明", "高祖": "朱元璋", "儿子":{"永乐大帝": "朱棣"}}
f = open("json.json", mode = "w", encoding = "utf-8")
json.dump(dic, f, ensure_ascii = False, indent = 4) # indent 缩进 4个空格 = 一个tab
# 读取json,转换成字典
f = open("json.json", mode = "r", encoding = "utf-8") # 打开文件
dic = json.load(f) # 把json转换成字典
print(dic)
3、把一个对象转换成json
class Car:
def __init__(self, name, color):
self.name = name
self.color =color
c = Car("宝马", "大红")
s = json.dumps(c.__dict__, ensure_ascii = False) # 方案一,通过__dict__,获得对象的字典,进行转换(转化的是字典)
print(s) # 转换json成功,
def func(obj):
return {
"self.name": obj.name,
"self.color": obj.color
}
s = json.dumps(c,default = func, ensure_ascii = False) # 方案二,通过函数,生成字典,来用json(转化的也是字典)
print(s)
# json转回对象
s = '{"name": "宝马", "color": "大红"}'
def func(dic):
return Car(dic["name"],dic["color"])
p = json.loads(s, object_hook = func) # 通过函数func把字典转换成对象
print(p.name, p.color)
五、configparser模块
该模块适⽤于配置⽂件的格式与windows的 ini⽂件类似,
可以包含⼀个或多个节(section)
每个节可以有多个参数(键=值).
⾸先, 我们先看⼀个xxx服务器的配置⽂件
import configparser
# config = configparser.ConfigParser() # 创建对象
#
# config['DEFAULT'] = { # 特殊的,默认的,其他所有的章节都含有他的内容,跟函数的类变量一样
# "name":"腾讯qq木马",
# "time":"qq更新时间",
# "version":"1.0"
# }
# config['SERVER_1'] = {
# "IP":"192.168.1.123",
# "port":"12306"
# }
# config['SERVER_2'] = {
# "IP":"192.168.1.178",
# "port":"12311"
# }
# config['SERVER_3'] = {
# "IP":"192.168.1.176",
# "port":"12312"
# }
#
# # 写入到文件
# config.write(open("qq.ini", mode="w", encoding="utf-8"))
# 读取内容
config = configparser.ConfigParser() # 创建对象,
# 读取内容
config.read("qq.ini", encoding="utf-8") # 此时我们把文件中的内容读取到config
print(config['SERVER_1']['IP']) # 字典
print(config['SERVER_2']['name'])
print(config.get("SERVER_3", "IP")) # 字典
for k, v in config['DEFAULT'].items():
print(k, v)
# 增删改操作:
# 先读取. 然后修改. 最后写回⽂件
# config = configparser.ConfigParser()
# # 读取内容
# config.read("qq.ini", encoding="utf-8") # 此时我们把文件中的内容读取到config
# config['SERVER_1']['NAME'] = "哈哈哈" # 增加
# 添加⼀个章节
# config.add_section("189-DB")
# config["189-DB"] = {
# "db_ip": "167.76.22.189",
# "port": "3306",
# "u_name": "root",
# "u_pwd": "123456"
# }
# 修改信息
config.set("SERVER_1", "IP", "10.10.10.168")
# 删除章节
config.remove_section("SERVER_2")
# 删除元素信息
config.remove_option("SERVER_3", "port")
# 写回文件
# config.write(open("qq.ini", mode="w",