模块(下)

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带了便利的同时也有搞乱源代码的风险!
posted @ 2021-08-17 21:35  停在夏季  阅读(33)  评论(0编辑  收藏  举报
-->