# 常用模块-02
# 序列化 把对象打散成二进制字节 bytes
# 1. pickle 把一个对象转化成bytes写入到文件
# pickle.dumps() 把对象转换成bytes
# pickle.loads() 把bytes转化成对象
#
# pickle.dump() 把对象转换成bytes. 写入到文件
# pickle.load() 把文件中的bytes读取. 转化成对象
#
# 2. shelve 小型数据库, redis, mongodb, dict
# 当成字典来用
# writeback=True
#
# 3. json 以前用xml 先在用json
# json.dumps() 把字典转换成json字符串
# json.loads() 把json字符串转化成字典
#
# json.dump() 把字典转换成json字符串. 写入到文件
# json.load() 把文件中的json字符串读取. 转化成字典
#
# default = 把对象转化成字典. 需要自己写转换过程
# object_hook = 把字典转化成对象. 需要自己写转换过程
#
# ensure_ascii = False 可以处理中文
# 4. configparser 处理windows配置文件的 dict
# 一、什么是序列化
# 在我们存储数据或者⽹络传输数据的时候. 需要对我们的对象进⾏处理. 把对象处理成
# ⽅便存储和传输的数据格式. 这个过程叫序列化. 不同的序列化, 结果也不同. 但是⽬的是⼀
# 样的. 都是为了存储和传输.
# 在python中存在三种序列化的⽅案.
# 1. pickle. 可以将我们python中的任意数据类型转化成bytes并写入到⽂件中. 同样也
# 可以把⽂件中写好的bytes转换回我们python的数据. 这个过程被称为反序列化
# 2. shelve. 简单另类的⼀种序列化的⽅案. 有点⼉类似后⾯我们学到的redis. 可以作为
# ⼀种⼩型的数据库来使⽤
# 3. json. 将python中常⻅的字典, 列表转化成字符串. 是⽬前前后端数据交互使⽤频率
# 最⾼的⼀种数据格式.
# 二、pickle
# 单独一个对象不涉及到文件写入用dumps和loads,涉及到对象写入文件用dump/load
# pickle⽤起来很简单. 说⽩了. 就是把我们的python对象写入到⽂
# import pickle
# class Cat:
# def __init__(self, name, age):
# self.name = name
# self.age = age
# def catchMouse(self):
# print(self.name, "抓⽼⿏")
# c = Cat("jerry", 18)
# bs = pickle.dumps(c) # 序列化⼀个对象.
# print(bs) # ⼀堆⼆进制. 看不懂
# cc = pickle.loads(bs) # 把⼆进制反序列化成我们的对象
# cc.catchMouse() # 猫依然是猫. 还可以抓⽼⿏
# 一次放入多只
# class Cat:
# def __init__(self, name, color):
# self.name = name
# self.color = color
#
# def chi(self):
# print("我家的%s猫吃人" %self.name)
#
# c = Cat("Tom", "黑色")
# c1 = Cat("Tom1", "黑色1")
# c2 = Cat("Tom2", "黑色1")
# c3 = Cat("Tom3", "黑色1")
# c4 = Cat("Tom4", "黑色1")
# lst = [c, c1, c2, c3, c4]
#
# cc = pickle.dump(lst, open("mao.dat", mode="wb")) # pickle模式可以直接将列表写入文件
# lis = pickle.load(open("mao.dat", mode="rb"))
# for s in lis:
# s.chi()
# 总结pickle:是先将对象打散成字节在写入文件中
# pickle面向对象完成登录注册
# import pickle
# class User:
# def __init__(self, username, password):
# self.username = username
# self.password = password
#
# class Main:
#
# def regiset(self):
# user = input("请输入你注册账号:")
# pwd = input("请输入你注册密码:")
# u = User(user, pwd)
# pickle.dump(u, open("maoo.dat", mode="ab"))
# print("注册成功!!!")
#
# def login(self):
# user = input("请输入你的账号:")
# pwd = input("请输入你的密码:")
# f = open("maoo.dat", mode="rb", )
# while True:
# try:
# u = pickle.load(f)
# # print(u.username)
# # print(u.password)
# if u.username == user and u.password == pwd:
# print("登录成功")
# break
# except Exception:
# print("登录失败")
# break
#
# Main().regiset()
# Main().regiset()
# Main().login()
# 三、shelve
# shelve提供python的持久化操作. 什么叫持久化操作呢? 说⽩话,就是把数据写到硬盘上.
# 在操作shelve的时候非常的像操作⼀个字典. 这个东⻄到后期. 就像redis差不多.
# import shelve
# d = shelve.open("shaobing")
# d["jj"] = "林俊杰"
# print(d["jj"]) # "林俊杰"
# d["jj"] = "周杰伦"
# print(d["jj"]) # "周杰伦"
# d.close()
# shelve小坑
# import shelve
# s = shelve.open("sylar")
# s["jay"] = {"name":"周杰伦", "age":18, "hobby":"哄⼩孩"}
# print(s['jay']) # {'name': '周杰伦', 'age': 18, 'hobby': '哄⼩孩'}
# s.close()
#
# s = shelve.open("sylar")
# s['jay']['name'] = "胡辣汤" # 尝试改变字典中的数据
# s.close()
#
# s = shelve.open("sylar")
# print(s['jay']) # # {'name': '周杰伦', 'age': 18, 'hobby': '哄⼩孩'} 并没有改变
# # 原因你改变了这一项可以理解成产生一个新的字典
# s.close()
# # 解决方案
# # 1、重新用一个新的中间变量
# s = shelve.open("sylar", writeback=True)
# s['jay']['name'] = "胡辣汤" # 尝试改变字典中的数据
# s.close()
# s = shelve.open("sylar")
# print(s['jay']) # 改变了.
# s.close()
# writeback=True可以动态的把我们修改的信息写入到⽂件中. ⽽且这个⿁东⻄还可以删
# 除数据. 就像字典⼀样. 上⼀波操作(相当于修改后再写入)
# s = shelve.open("sylar", writeback=True)
# del s['jay']
# s.close()
# s = shelve.open("sylar")
# print(s['jay']) # 报错了, 没有了
# s.close()
# s = shelve.open("sylar", writeback=True)
# s['jay'] = "周杰伦"
# s['wlj'] = "王⼒宏"
# s.close()
# s = shelve.open("sylar")
# for k in s: # 像字典⼀样遍历
# print(k)
# print(s.keys()) # 拿到所有key的集合
# for k in s.keys():
# print(k)
# for k, v in s.items(): # 像字典⼀样操作
# print(k, v)
# s.close()
# 四、json
# json是我们前后端交互的枢纽. 相当于编程界的普通话. ⼤家沟通都⽤
# json. 为什么这样呢? 因为json的语法格式可以完美的表⽰出⼀个对象. 那什么是json: json全
# 称javascript object notation. 翻译过来叫js对象简谱. 很复杂是吧? 来上⼀段我们认识的代
# 码:
# wf = {
# "name":"汪峰",
# "age":18,
# "hobby":"上头条",
# "wife":{
# "name":'⼦怡',
# "age":19,
# "hobby":["唱歌", "跳舞", "演戏"]
# }
# }
# 在python⾥这玩意叫字典. 但是在javascript⾥这东⻄叫json. ⼀
# 模⼀样的. 我们发现⽤这样的数据结构可以完美的表⽰出任何对象. 并且可以完整的把对象
# 表⽰出来. 只要代码格式比较好. 那可读性也是很强的. 所以⼤家公认⽤这样⼀种数据结构作
# 为数据交互的格式.
# import json
# dic = {"烽火": "戏诸侯", "江山": "美人", "少年": "很骚", "哈哈":False}
# # d = json.dumps(dic) #{"u70fdu706b": "u620fu8bf8u4faf", "u6c5fu5c71": "u7f8eu4eba", "u5c11u5e74": "u5f88u9a9a"} #写成字节
# d = json.dumps(dic, ensure_ascii= False)
# print(d) # {"烽火": "戏诸侯", "江山": "美人", "少年": "很骚", "哈哈": false}
# print(type(d)) # <class 'str'>
# s = '{"烽火": "戏诸侯", "江山": "美人", "少年": "很骚", "哈哈": false}'
# s1 = json.loads(s) # 将s转化为字典
# print(s1) # {'烽火': '戏诸侯', '江山': '美人', '少年': '很骚', '哈哈': False}
# print(type(s1)) # <class 'dict'>
# dic = {"烽火": "戏诸侯", "江山": "美人", "少年": "很骚", "哈哈": False, "wf": {"name": "王分", "hobby": "皮裤"}}
# d = json.dump(dic, open("江山", mode="w", encoding="utf-8"), ensure_ascii=False, indent=4)
# d1 = json.load(open("江山", mode="r", encoding="utf-8"))
# print(d1)
#对象怎么写入文件 怎么拿?
# class Person:
# def __init__(self, name, gender):
# self.name = name
# self.gender = gender
# p = Person("黑皮", "男")
# print(p.__dict__)
# s = json.dumps(p.__dict__, ensure_ascii=False)
# print(s)
# def func(obj):
# return {
# "name": obj.name,
# "gender": obj.gender
# }
# s1 = json.dumps(p, default=func, ensure_ascii=False)
# print(s1)
# x = '{"name": "黑皮", "gender": "男"}' # json字符串里面只能用双引号,外面用单引号
# def func(obj):
# return Person(obj["name"], obj["gender"])
# x1 = json.loads(x, object_hook=func)
# print(x1.name)
# 五、configparser模块
# 该模块适用于配置文件格式与windows ini文件类似,可以包含一个或多个节(section)
# 每个节可以有多个参数(键=值)
# 手动配置文件
import configparser # 将config文件看成一个大字典、里面套的是小字典(操作和字典相似)
config = configparser.ConfigParser()
config["DEFAULT"] = { # ["DEFAULT"] 这一项是配置默认文件,下面的每一项默认都带着"DEFAULT"中的每一项
"sleep": 1000,
"session-time-out": 30,
"user-alive": 99999
}
config["TEST-DB"] = {
"db_ip": "192.168.17.189",
"port": "3306",
"u_name": "root",
"u_pwd": "123456"
}
config['168-DB'] = {
"db_ip": "152.163.18.168",
"port": "3306",
"u_name": "root",
"u_pwd": "123456"
}
config["173-DB"] = {
"db_ip": "152.163.18.173",
"port": "3306",
"u_name": "root",
"u_pwd": "123456"
}
f = open("date.ini", mode="w", encoding="utf-8")
config.write(f) # 写入文件
f.flush()
f.close()
# 读取文件:
# config = configparser.ConfigParser()
# config.read("date.ini") # 读取文件
# print(config.sections()) #['TEST-DB', '173-DB'] 获取到section. 章节...DEFAULT是给每个章节都配备的信息
# print(config.get("DEFAULT", "SESSION-TIME-OUT")) # 30 从xxx章节中读取到xxx信息
# print(config["TEST-DB"]['DB_IP']) # 192.168.17.189
# print(config["173-DB"]["db_ip"]) # 152.163.18.173
# 将config看成一个字典操作就行
# for k in config['168-DB']:
# print(k)
# 结果:
# db_ip
# port
# u_name
# u_pwd
# sleep
# session-time-out
# user-alive
# print(config.options('168-DB')) # ['db_ip', 'port', 'u_name', 'u_pwd', 'sleep', 'session-time-out', 'user-alive'] 同for循环,找到'168-DB'下所有键
# print(config.items('168-DB')) #找到'168-DB'下所有键值对
# print(config.get('168-DB','db_ip')) # 152.163.18.168 get⽅法Section下的key对应的value
# 先读取. 然后修改. 最后写回⽂件
config = configparser.ConfigParser()
config.read("date.ini") # 读取⽂件
# 添加⼀个章节
config.add_section("189-DB")
config["189-DB"] = {
"db_ip": "167.76.22.189",
"port": "3306",
"u_name": "root",
"u_pwd": "123456"
}
# 修改信息
config.set("168-DB", "db_ip", "10.10.10.168")
# 删除章节
config.remove_section("173-DB")
# 删除元素信息
config.remove_option("168-DB", "u_name")
# 写回⽂件
config.write(open("db.ini", mode="w"))