一 json与pickle模块
1.1 什么是序列化和反序列化
我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化
内存中的数据类型---->序列化---->特定的格式(json格式或者pickle格式)
内存中的数据类型<----反序列化<----特定的格式(json格式或者pickle格式)
1.2 为什么要有序列化
1、可用于存储=>用于存档
2、传输给其他平台使用=>跨平台数据交互
强调:
针对用途1的特定一格式:可是一种专用的格式=>pickle只有python可以识别
针对用途2的特定一格式:应该是一种通用、能够被所有语言识别的格式=>json
1.3 如何使用这两种模块
序列化:
import json json_res = json.dumps([1,'asfas',True,False]) print(json_res,type(json_res)) # 序列化的结果写入文件的复杂方法 json_res = json.dumps([1,'asfas',True,False]) with open('a.json','wt',encoding='utf-8')as f: f.write(json_res) # 将序列化的结果写入文件的简单方法 with open('a.json','wt',encoding='utf-8')as f: json.dump([1,'asfas',True,False],f)
反序列化
import json l = json.loads(json_res) print(l,type(l)) # 从文件读取json格式的字符串进行反序列化操作的复杂方法 with open('a.json',mode='rt',encoding='utf-8') as f: json_res=f.read() l=json.loads(json_res) print(l,type(l)) # 从文件读取json格式的字符串进行反序列化操作的简单方法 with open('a.json',mode='rt',encoding='utf-8') as f: l=json.load(f) print(l,type(l))
json强调:
#json格式兼容的是所有语言通用的数据类型,不能识别某一语言的所独有的类型 json.dumps({1,2,3,4,5})#集合是py独有的,json不兼容,报错 #一定要搞清楚json格式,不要与python混淆 l=json.loads("[1,1.3,true,'aaa', true, false]") #json格式的字符串是双引号,报错
了解
# 在python解释器2.7与3.6之后都可以json.loads(bytes类型),但唯独3.5不可以 l = json.loads(b'[1, "aaa", true, false]') print(l, type(l))

# 一.什么是猴子补丁? 猴子补丁的核心就是用自己的代码替换所用模块的源代码,详细地如下 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带了便利的同时也有搞乱源代码的风险!
模块pickle
#如果要从文件读取来用b模式 import pickle res=pickle.dumps({1,2,3,4,5}) print(res,type(res)) s=pickle.loads(res) print(s,type(s))

import pickle with open('a.pkl',mode='wb') as f: # 一:在python3中执行的序列化操作如何兼容python2 # python2不支持protocol>2,默认python3中protocol=4 # 所以在python3中dump操作应该指定protocol=2 pickle.dump('你好啊',f,protocol=2) with open('a.pkl', mode='rb') as f: # 二:python2中反序列化才能正常使用 res=pickle.load(f) print(res)
二 shelve 与xml 模块(了解)
shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型

import shelve f=shelve.open(r'sheve.txt') # f['stu1_info']={'name':'egon','age':18,'hobby':['piao','smoking','drinking']} # f['stu2_info']={'name':'gangdan','age':53} # f['school_info']={'website':'http://www.pypy.org','city':'beijing'} print(f['stu1_info']['hobby']) f.close()
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml。
xml的格式如下,就是通过<>节点来区别数据结构的:

<?xml version="1.0"?> <data> <country name="Liechtenstein"> <rank updated="yes">2</rank> <year>2008</year> <gdppc>141100</gdppc> <neighbor name="Austria" direction="E"/> <neighbor name="Switzerland" direction="W"/> </country> <country name="Singapore"> <rank updated="yes">5</rank> <year>2011</year> <gdppc>59900</gdppc> <neighbor name="Malaysia" direction="N"/> </country> <country name="Panama"> <rank updated="yes">69</rank> <year>2011</year> <gdppc>13600</gdppc> <neighbor name="Costa Rica" direction="W"/> <neighbor name="Colombia" direction="E"/> </country> </data> xml数据
xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml:
# print(root.iter('year')) #全文搜索 # print(root.find('country')) #在root的子节点找,只找一个 # print(root.findall('country')) #在root的子节点找,找所有

import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml") root = tree.getroot() print(root.tag) #遍历xml文档 for child in root: print('========>',child.tag,child.attrib,child.attrib['name']) for i in child: print(i.tag,i.attrib,i.text) #只遍历year 节点 for node in root.iter('year'): print(node.tag,node.text) #--------------------------------------- import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml") root = tree.getroot() #修改 for node in root.iter('year'): new_year=int(node.text)+1 node.text=str(new_year) node.set('updated','yes') node.set('version','1.0') tree.write('test.xml') #删除node for country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country) tree.write('output.xml')

#在country内添加(append)节点year2 import xml.etree.ElementTree as ET tree = ET.parse("a.xml") root=tree.getroot() for country in root.findall('country'): for year in country.findall('year'): if int(year.text) > 2000: year2=ET.Element('year2') year2.text='新年' year2.attrib={'update':'yes'} country.append(year2) #往country节点下添加子节点 tree.write('a.xml.swap')

import xml.etree.ElementTree as ET new_xml = ET.Element("namelist") name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"}) age = ET.SubElement(name,"age",attrib={"checked":"no"}) sex = ET.SubElement(name,"sex") sex.text = '33' name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"}) age = ET.SubElement(name2,"age") age.text = '19' et = ET.ElementTree(new_xml) #生成文档对象 et.write("test.xml", encoding="utf-8",xml_declaration=True) ET.dump(new_xml) #打印生成的格式
三 configparser模块
txt.ini配置文件内容
# 注释1 ; 注释2 [section1] k1 = v1 k2:v2 user=egon age=18 is_admin=true salary=31 [section2] k1 = v1
读取操作
import configparser config=configparser.ConfigParser() config.read('txt.ini') #查看所有的标题 res=config.sections() print(res)#['section1', 'section2'] #查看标题section1下所有key=value的key options=config.options('section1') print(options) #['k1', 'k2', 'user', 'age', 'is_admin', 'salary'] #查看标题section1下所有key=value的(key,value)格式 item_list=config.items('section1') print(item_list) #[('k1', 'v1'), ('k2', 'v2'), ('user', 'egon'), ('age', '18'), ('is_admin', 'true'), ('salary', '31')] #查看标题section1下user的值=>字符串格式 val=config.get('section1','user') print(val) #egon #查看标题section1下age的值=>整数格式 val1=config.getint('section1','age') print(val1) #18 #查看标题section1下is_admin的值=>布尔值格式 val2=config.getboolean('section1','is_admin') print(val2) #True #查看标题section1下salary的值=>浮点型格式 val3=config.getfloat('section1','salary') print(val3) #31.0
四 hashlib模块
4.1 什么是hash
hash一类算法,该算法接受传入的内容,经过运算得到一串hash值
hash值的特点:
1 只要传入的内容一样,得到的hash值必然一样
2 不能由hash值返解成内容
3 不管传入的内容有多大,只要使用的hash算法不变,得到的hash值长度是一定
4.2 hash的用途
用途1:特点2用于密码密文传输与验证
用途2:特点1,3用于文件完整性校验
4.3 如何使用hash
import hashlib # md5可以换成其他的加密方式 m=hashlib.md5() m.update('hello'.encode('utf-8')) m.update('world'.encode('utf-8')) res=m.hexdigest() # 'helloworld' print(res) # 验证特点1 m1=hashlib.md5('he'.encode('utf-8')) m1.update('llo'.encode('utf-8')) m1.update('w'.encode('utf-8')) m1.update('orld'.encode('utf-8')) res=m1.hexdigest()# 'helloworld' print(res)
大文件快速进行比对效验
# 文件过大要进行比对会很慢:我们可以通过指针的随机选取位置来进行效验,这样就加快了速度 import hashlib m=hashlib.md5() f=open('a.txt',mode='rb') f.seek() f.read(2000) m.update(文件的一行) m.hexdigest()
模拟撞库
cryptograph='aee949757a2e698417463d47acac93df' import hashlib # 制作密码字段 passwds=[ 'alex3714', 'alex1313', 'alex94139413', 'alex123456', '123456alex', 'a123lex', ] dic={} for p in passwds: res=hashlib.md5(p.encode('utf-8')) dic[p]=res.hexdigest() # 模拟撞库得到密码 for k,v in dic.items(): if v == cryptograph: print('撞库成功,明文密码是:%s' %k) break
提升撞库的成本——>密码加盐:防止撞库的成功率
import hashlib m=hashlib.md5() m.update('天王'.encode('utf-8')) m.update('alex3714'.encode('utf-8')) m.update('盖地虎'.encode('utf-8')) print(m.hexdigest())
五 suprocess模块
import subprocess
#就是运行命令 把运行结果放到管道中
obj=subprocess.Popen('echo 123 ; ls / ; ls /root',shell=True,#shell就是打开cmd
stdout=subprocess.PIPE, #正确管道
stderr=subprocess.PIPE, #错误管道
)
print(obj)
res=obj.stdout.read()
print(res.decode('utf-8'))
err_res=obj.stderr.read()
print(err_res.decode('utf-8'))