本节内容:
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",