模块(下)
shelve模块
import shelve
# 序列化
# f = shelve.open(r'sheve.txt')
# f['stu1_info'] = {'name': 'EGON', 'age': 28, 'hobby': ['piao', 'smoking', 'drinking']}
# f['stu2_info'] = {'name': 'gangdan', 'age': 53}
# f['school_info'] = 123123123123123123123123123
# f['test'] = {1,2,3,4,5}
#
# # print(f['stu1_info']['hobby'])
# f.close()
# 反序列化
import shelve
f=shelve.open(r'sheve.txt')
print(f['stu1_info']['name'])
print(f['school_info'])
print(f['test'])
f.close()
configparser模块(加载某种特定格式文件)(获取配置文件配置项)
config.ini文件
#注释1
注释2
[section1]
k1=v1
k23:v2
user=egon
age=18
is_admin=true
salary=31
[section2]
k1=v1
import configparser
config = configparser.ConfigParser()
config.read('config.ini')
# res = config.sections()
# print(res)
# res = config.options('section1')
# print(res) # 获取config文件所有options(key) 结果 ['k1'....'salary' ]
# res = config.items('section1')
# print(res) # 获取config文件所有item(key,value)结果[('k1','v1')...('salary','31' )]
# res = config.get('section1','is_admin') #获取指定需求
# res = bool(res)
# res = config.getboolean('section1','is_admin')
# print(res,type(res))
# res = config.get('section1','salary')
# res = config.getfloat('section1','salary')
res = config.getint('section1','salary')
print(res,type(res))
hashlib模块
hash是一种算法
(3.x里代替了md5模块和sha模块,
主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法)
该算法接受传入的内容,经过运算得到一串hash值
hash算法就像一座工厂,工厂接收你送来的原材料
(可以用m.update()为工厂运送原材料),
经过加工返回的产品就是hash值
hash值的特点是:
只要传入的内容一样,得到的hash值必然一样=====>要用明文传输密码文件完整性校验
不能由hash值返解成内容=======》把密码做成hash值,不应该在网络传输明文密码
只要使用的hash算法不变,无论校验的内容有多大,得到的hash值长度是固定的
import hashlib
m=hashlib.md5()# m=hashlib.sha256()
m.update('hello'.encode('utf8'))
print(m.hexdigest())
#5d41402abc4b2a76b9719d911017c592
m.update('alvin'.encode('utf8'))
print(m.hexdigest())
#92a7e713c30abbb0319fa07da2a5c4af
m2=hashlib.md5()
m2.update('helloalvin'.encode('utf8'))
print(m2.hexdigest())
#92a7e713c30abbb0319fa07da2a5c4af
**注意**:把一段很长的数据update多次,与一次update这段长数据,
得到的结果一样但是update多次为校验大文件提供了可能。
import hashlib
with open(r'D:\视频\01 日志模块.mp4',mode='rb') as f:
m = hashlib.md5()
for line in f:
m.update(line)
print(m.hexdigest())
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>
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()
日志级别与配置
import logging
# 一:日志配置
logging.basicConfig(
# 1、日志输出位置:1、终端 2、文件
# filename='access.log', # 不指定,默认打印到终端
# 2、日志格式
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
# 3、时间格式
datefmt='%Y-%m-%d %H:%M:%S %p',
# 4、日志级别
# critical => 50
# error => 40
# warning => 30
# info => 20
# debug => 10
level=30,
)
**# 二:输出日志**
logging.debug('调试debug')
logging.info('消息info')
logging.warning('警告warn')
logging.error('错误error')
logging.critical('严重critical')
'''
# **注意**下面的root是默认的日志名字
WARNING:root:警告warn
ERROR:root:错误error
CRITICAL:root:严重critical
'''
LOGGING_DIC = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'格式1': {
'format': '%(asctime)s %(name)s %(filename)s:%(lineno)d %(levelname)s:%(message)s'
},
'格式2': {
'format': '%(asctime)s :%(message)s'
},
},
'filters': {},
'handlers': {
'屏幕': {
'level': 'DEBUG',
'class': 'logging.StreamHandler', # 打印到屏幕
'formatter': '格式2'
},
'文件': {
'level': 'DEBUG',
'class': 'logging.FileHandler', # 保存到文件
'formatter': '格式1',
'filename': LOG_PATH,
'encoding': 'utf-8',
},
},
'loggers': {
'交易日志': {
'handlers': ['屏幕','文件'],
'level': 'DEBUG',
'propagate': False,
},
'': {
'handlers': ['屏幕','文件'],
'level': 'DEBUG',
'propagate': False,
},
},
}
猴子补丁(将源代码当中的某些功能替换成自己的功能的操作,应该放到程序入口的执行文件去操作)(好处:在入口打完补丁所有位置都跟着改,不用了可以直接在入口删除)
二. 猴子补丁的功能(一切皆对象)
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带了便利的同时也有搞乱源代码的风险!