17--常用模块02:json、猴子补丁、configparse、hashlib、subprocess
作者:互联网
1.json&pickle模块
# 0.eval内置方法可以将一个字符串转成python对象
eval的重点还是通常用来执行一个字符串表达式,并返回表达式的值
缺点:eval方法是有局限性的,对于特殊类型,识别不了
import json
x="[null,true,false,1]"
print(eval(x)) # 报错,无法解析null类型,而json就可以
print(json.loads(x))
# 1.什么是序列化&反序列化
序列化指的是把内存的数据类型转成一个特定的格式
该格式的内容可用于存储或传输给其他平台使用
内存中的数据类型--->序列化--->特定的格式(json格式或者pickle格式)
内存中的数据类型<---反序列化<---特定的格式(json格式或者pickle格式)
土办法:
将字典存储到硬盘中:
{'aaa':111}--->序列化str({'aaa':111})--->"{'aaa':111}"
读取硬盘中数据,转化为字典
{'aaa':111}<---反序列化eval("{'aaa':111}")<---"{'aaa':111}"
Python中叫pickling,其他语言被称之为serialization,marshalling,flattening等等
# 2.为何要序列化
序列化得到结果=》特定的格式的内容有两种用途
1.可用于存储=》用于存档
2.传输给其他平台使用=》跨平台数据交互
python java
列表 特定的格式 数组
强调:
针对用途1:可是一种专用的格式==》pickle # 只有python可以识别
针对用途2:应该是一种通用、能够被所有语言识别的格式==》json
1.1 json模块
若是给其他语言使用(跨平台数据交互),就序列化成json格式
# 3.如何序列化与反序列化
# 示范1
import json
# 序列化
json_res=json.dumps([1,'aaa',True,False])
print(json_res,type(json_res)) # "[1, "aaa", true, false]"
# 反序列化
l=json.loads(json_res)
print(l,type(l))
# 示范2:
# 序列化的结果写入文件的复杂方法
# ---->先序列化字符串,再单纯的写入文件
json_res=json.dumps([1,'aaa',True,False])
with open('test.json',mode='wt',encoding='utf-8') as f:
f.write(json_res)
# 将序列化的结果写入文件的简单方法 (使用这个)
# --->直接序列化成文件格式
with open('test.json',mode='wt',encoding='utf-8') as f:
json.dump([1,'aaa',True,False],f)
# 从文件读取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))
# 从文件读取json格式的字符串进行反序列化操作的简单方法 (使用这个)
with open('test.json',mode='rt',encoding='utf-8') as f:
l=json.load(f)
print(l,type(l))
# 总结:
json.dumps(str) 字符串 --> 序列化 --> json字符串
json.loads(json) json字符串 --> 反序列化 --> 字符串
json.dump(str,f) 序列化,并存到f文件中
json.load(f) 从f文件中,反序列化
json格式
1.2 json 补充
# json验证: json格式兼容的是所有语言通用的数据类型,不能识别某一语言所独有的类型
json.dumps({1,2,3,4,5}) # 错误,集合不能序列化
# json强调:一定要搞清楚json格式,不要与python混淆
l=json.loads('[1, "aaa", true, false]')
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))
# 故反序列文件,可以直接以bytes类型打开
with open('test.json',mode='rb') as f:
l=json.load(f)
res=json.dumps({'name':'哈哈哈'})
print(res,type(res))
res=json.loads('{"name": "\u54c8\u54c8\u54c8"}')
print(res,type(res))
1.3 猴子补丁
# 一.什么是猴子补丁?
属性在运行时的动态替换,叫做猴子补丁(Monkey Patch)。
猴子补丁的核心就是用自己的代码替换所用模块的源代码,来源如下:
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() # word
monkey.world = other_func
monkey.world() # from other_func
# 三.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()
# 之所以在入口处加,是因为模块在导入一次后,后续的导入便直接引用第一次的成果
# 实际场景:
1.用新模块替换原来的模块
2.丰富模块的功能, 除了继承之外也可以考虑用Monkey Patch
好处:
采用猴子补丁之后,如果发现ujson不符合预期,那也可以快速撤掉补丁
缺点:
MonkeyPatch带了便利的同时也有搞乱源代码的风险!
1.4 pickle模块
若是python自己使用(数据存档),就序列化成pickle格式
import pickle
# 序列化
res=pickle.dumps({1,2,3,4,5})
print(res,type(res)) # pickle模块序列化是bytes类型
# 反序列化
s=pickle.loads(res)
print(s,type(s))
# 总结:
pickle.dumps(str) 字符串 --> 序列化 --> pickle序列化bytes类型
pickle.loads(json) pickle序列化bytes类型 --> 反序列化 --> 字符串
pickle.dump(str,f) 序列化,并存到f文件中
pickle.load(f) 从f文件中,反序列化
# python2与python3的pickle兼容性问题
# 1.在python3中,执行的序列化操作 如何兼容python2
python2不支持protocol>2,默认python3中protocol=4
故:python3中dump操作 应该指定protocol=2
# coding:utf-8
import pickle
with open('a.pkl',mode='wb') as f:
pickle.dump('你好啊',f,protocol=2)
# python2中,反序列化才能正常使用
with open('a.pkl', mode='rb') as f:
res=pickle.load(f)
print(res)
2.shelve 模块(了解)
# shelve模块: 以字典的形式序列化存储 数据 shelve:书架,搁置
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()
3.configparser模块
# 配置文件: 常用格式后缀 ".ini"
# 注释1
; 注释2
[section1] # 以section:部分 来划分几个部分
k1 = v1 # option:项 '=' 或者 ':' 值
k2:v2
user=egon
age=18
is_admin=true
salary=31
[section2]
k1 = v1
3.1 读取配置文件
# 用来处理固定格式的配置文件 configparser 配置解析
import configparser
config=configparser.ConfigParser() # 首先实例化类-对象
config.read('test.ini') # .read() 读取配置文件
# 1.获取sections
print(config.sections()) # ['section1', 'section2']
# 2.获取某一section下的所有options
print(config.options('section1')) # ['k1', 'k2'...]
# 3.获取items
print(config.items('section1')) # [('k1', 'v1'), ('k2', 'v2')...]
# 4.获取-某部分-某项的值
res=config.get('section1','user')
print(res,type(res)) # egon str
# 5.获取-某部分-某项的值,并转化成数字格式
res=config.getint('section1','age')
print(res,type(res)) # 18 int
# 6.获取-某部分-某项的值,并转化成布尔格式
res=config.getboolean('section1','is_admin')
print(res,type(res)) # True bool
# 7.获取-某部分-某项的值,并转化成浮点数格式
res=config.getfloat('section1','salary')
print(res,type(res)) # 31.0 float
3.2 改写配置文件
import configparser
config=configparser.ConfigParser()
config.read('a.cfg',encoding='utf-8')
# 删除整个标题section2
config.remove_section('section2')
# 删除标题section1下的某个k1和k2
config.remove_option('section1','k1')
config.remove_option('section1','k2')
# 判断是否存在某个标题
print(config.has_section('section1'))
# 判断标题section1下是否有user
print(config.has_option('section1','user'))
# 添加一个标题
config.add_section('egon')
# 在标题egon下添加name=egon,age=18的配置
config.set('egon','name','egon')
config.set('egon','age',18) # 报错,必须是字符串
# 将修改的内容 写入到某个文件对象,完成最终的修改
config.write(open('a.cfg','w'))
4.hashlib模块
# 1.什么是哈希hash
hash是一类算法,该算法接受传入的内容,经过运算得到一串hash值
3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5算法
# 2.hash值的特点:
1.只要传入的内容一样,和hash的算法一样,得到的hash值必然一样
2.不能由hash值反解成内容
3.不管传入的内容有多大,只要使用的hash算法不变,得到的hash值长度是一定
好处是:不会随着传入的内容越大而扩大hash长度,节约传输空间
# 3.hash的用途
用途1:特点2用于密码密文传输与验证
用途2:特点1、3用于文件完整性校验
# 4.如何用
import hashlib
m=hashlib.md5() # 调用hashlib库下的各种hash算法函数,也可以直接传参-->要hash的内容
m.update('hello'.encode('utf-8')) # .update() 上传 要hash的内容
m.update('world'.encode('utf-8')) # 传入要hash的内容必须是 bytes类型
res=m.hexdigest() # 'helloworld' # .hexdigest() 拿到hash值
print(res)
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' hash结果一样
print(res)
md5:是32位加密
# 模拟撞库
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
# 提升撞库的成本=>密码加盐 (在原有密码上 加上 一段暗号,且自己定制排列组合--->再去hash)
import hashlib
m=hashlib.md5()
m.update('天王'.encode('utf-8'))
m.update('alex3714'.encode('utf-8'))
m.update('盖地虎'.encode('utf-8'))
print(m.hexdigest())
# 校验文件完整性
# 文件特别大时,全部hash比对浪费时间和效率
m.update(文件所有的内容)
m.hexdigest()
# 应当随机读取几个部分的内容 进行hash值比对
f=open('a.txt',mode='rb')
f.seek() # 移动文件指针几个位置
res = f.read(2000) # 读取固定长度的字节
m1.update(res)
m1.hexdigest()
5.subprocess模块
# suprocess是用来执行系统命令,并查看结果的
# 原理:
利用suprocess模块下标准输出流,标准输入流,标准错误流,
且输出格式是bytes类型,方便我们查看调用系统命令后的结果
import subprocess
# subprocess.Popen() 对象实例化该类
第一个参数:'系统命令'
shell=True : Linux系统下调用终端端口
stdout=subprocess.PIPE :将执行系统命令的正确结果,放进PIPE管道,并给stdout
stderr=subprocess.PIPE :把返回的错误结果放在stderr管道
obj=subprocess.Popen('echo 123 ; ls / ; ls /root',shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
# 读取执行命令后的 正确结果
res=obj.stdout.read()
print(res.decode('utf-8'))
# 读取执行命令后的 错误结果
err_res=obj.stderr.read()
print(err_res.decode('utf-8'))
标签:02,configparse,hash,17,res,json,print,序列化,config 来源: https://www.cnblogs.com/Edmondhui/p/16400070.html