Python学习日记(二十八) hashlib模块、configparse模块、logging模块

2023-07-11,,

hashlib模块

主要提供字符加密算法功能,如md5、sha1、sha224、sha512、sha384等,这里的加密算法称为摘要算法。什么是摘要算法?它又称为哈希算法、散列算法,它通过一个函数把任意长度的数据转换为一个长度固定的数据串(通常以16进制符表示)

摘要算法的作用主要在于密码的密文存储,以及文件的一致性验证(比如在下载的时候,检查我们下载的文件和远程服务器上的文件是否一致;两台机器上的两个文件,检查上面的文件是否相等)

使用md5算法:

import hashlib
md5 = hashlib.md5()
md5.update(b'python123') #这里传入的数据类型必须是bytes类型
print(md5.hexdigest()) #affaf271b3ebb2db157a04874259cdcb

使用sha1算法:

import hashlib
sha1 = hashlib.sha1()
sha1.update(b'python123') #这里传入的数据类型必须是bytes类型
print(sha1.hexdigest()) #1854a7d8c2651e57acc7771b6644dfbf46b8ec98

使用sha512算法:

import hashlib
sha512 = hashlib.sha512()
sha512.update(b'python123') #这里传入的数据类型必须是bytes类型
print(sha512.hexdigest()) #e0420e412c80aaa3ce59408884317104dbc708f49bec8542574d11459ffda18ecb12489
#acf7893fd58ab2b57b8164c9d981096e5dfdbe6518423000301047fe6

从上面我们可以发现不管算法有多么不同,摘要的功能始终是不变的;对于相同的字符串使用同一个算法进行摘要,得到的值总是不变的;

使用不同的算法对相同的字符串进行摘要,得到的值应该不同;当使用sha算法时,随着算法的复杂难度的增加,摘要的时间成本和空间成本都会增加。

模拟用户登录:

我们创建一个'DB'的txt文档,并在里面写入用户信息

asd|affaf271b3ebb2db157a04874259cdcb
import hashlib
usn = input('Input username:')
pw = input('Input password:')
with open ('DB') as f:
for lines in f:
username,password = lines.split('|')
md5 = hashlib.md5()
md5.update(bytes(pw,encoding='utf-8'))
md5_pwd = md5.hexdigest()
if usn == username and md5_pwd == password:
print('登入成功!')
else:
print('登入失败!')
# Input username:asd
# Input password:python123
# 登入成功!

因此网站上的用户名及用户密码都是将它们转化成一个密令存放到数据库中,而对于开发工作者他们并不能直接看到用户的信息,只能看到由算法产生的密令。既然有了加密的算法来保护数据,那么也就会有人想要通过其他手段去获得用户的信息,他们主要根据一个数据库的密令全集去比对密令是否相等,如果相等那么就可以拿到这个用户的密码了。

'加盐'

import hashlib
#没加盐
md5 = hashlib.md5()
md5.update(b'')
print(md5.hexdigest()) #202cb962ac59075b964b07152d234b70 #加了盐
md5 = hashlib.md5(bytes('salt',encoding='utf-8'))
md5.update(b'')
print(md5.hexdigest()) #8c4fb7bf681156b52fea93442c7dffc9

加了盐后能够让用户的信息不能够直接通过一个数据全集将用户密码的密令去比对出来,让用户信息更有安全性

其他

import hashlib
#不拆分
md5 = hashlib.md5()
md5.update(b'')
print(md5.hexdigest()) #202cb962ac59075b964b07152d234b70 #拆分
md5 = hashlib.md5()
md5.update(b'')
md5.update(b'')
md5.update(b'')
print(md5.hexdigest()) #202cb962ac59075b964b07152d234b70

把数据拆开去加密和拆开去加密其实最后的结果都是一样的

configparser模块

该模块适用于配置文件的格式与windows ini文件类似,可以包含一个或多个节(section),每个节可以有多个参数(键=值)

利用configparser生成的文件格式

[DEFAULT]
location = upper left
visible = yes
editable = no
color = blue [main]
title = Main Menu
color = green [options]
title = Options

如何利用python生成这样一个文档?

# [DEFAULT]
# location = upper left
# visible = yes
# editable = no
# color = blue
#
# [main]
# title = Main Menu
# color = green
#
# [options]
# title = Options
import configparser
config = configparser.ConfigParser()
config['DEFAULT'] = {'location' : 'upper left',
'visible' : 'yes',
'color' : 'blue'} config['main'] = {}
config['main']['title'] = 'Main Meue'
config['main']['color'] = 'green' config['options'] = {}
config_op = config['options']
config_op['title'] = 'Options' config['DEFAULT']['editable'] = 'no'
with open ('config.ini','w') as configfile:
config.write(configfile)

import configparser
config = configparser.ConfigParser() print(config.sections())  #[]
config.read('config.ini')
print(config.sections())  #['main', 'options'] print('main' in config)  #True
print('options' in config)  #True
print('Options' in config)  #False print(config['main'])  #<Section: main>
print(config['options'])  #<Section: options> print(config['main']['color'])  #green
print(config['options']['title'])  #Options for key in config['main']: #title
print(key) #color
#location
#visible
#editable 注意,有default会默认default的键 print(config.options('main')) #['title', 'color', 'location', 'visible', 'editable'] print(config.items('main')) #[('location', 'upper left'), ('visible', 'yes'), ('color', 'green'),
                       #('editable', 'no'), ('title', 'Main Meue')] print(config.get('main','visible')) #yes 获得该键下对应的值

增删改

import configparser
config = configparser.ConfigParser()
config.read('config.ini') config.add_section('map') #增加一个新的节 config.remove_section('options') #删除一个节
config.remove_option('main','color') config.set('map','k1','v1')
config.set('main','k2','v2') config.write(open('config.ini','w')) # [DEFAULT]
# location = upper left
# visible = yes
# color = blue
# editable = no
#
# [main]
# title = Main Meue
# k2 = v2
#
# [map]
# k1 = v1

logging模块

即日志模块,即主要用来记录用户的行为或者代码的执行过程

这里定义了几种日志等级:

DEBUG:最详细的日志信息,典型应用场景是应用诊断

INFO:信息详尽程度仅次于DEBUG,通常只记录关键节点信息,用于确认一切是按照我们预期的那样进行工作

WARNING:当某些不期望的事情发生时记录的信息(如磁盘可用空间较低),但是此时应用程序还是正常运行的

ERROR:由于一个更严重的问题导致某些功能不能正常运行时记录的信息

CRITICAL:当发生严重错误,导致应用程序不能继续运行时记录的信息

日志的等级:DEBUG < INFO < WARNING < ERROR < CRITICAL

配置一个简单的日志:

import logging
logging.debug('DEBUG!')
logging.info('INFO!')
logging.warning('WARNING!')
logging.error('ERROR!')
logging.critical('CRITICAL')
# WARNING:root:WARNING!
# ERROR:root:ERROR!
# CRITICAL:root:CRITICAL

根据输出的结果我们可以看到这里只打印出了高于INFO级别的日志,可以说这里的默认级别设置为WARNING

默认的输出格式为默认的日志格式为日志级别:Logger名称:用户输出消息

通过basicConfig()调整日志级别和输出格式

import logging
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)s %(levelname)s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %a'
)
logging.debug('DEBUG!')
logging.info('INFO!')
logging.warning('WARNING!')
logging.error('ERROR!')
logging.critical('CRITICAL')
# 2019-09-12 00:40:11 Thu root DEBUG DEBUG!
# 2019-09-12 00:40:11 Thu root INFO INFO!
# 2019-09-12 00:40:11 Thu root WARNING WARNING!
# 2019-09-12 00:40:11 Thu root ERROR ERROR!
# 2019-09-12 00:40:11 Thu root CRITICAL CRITICAL

basicConfig的参数

filename:指日志输出目标文件的文件名

filemode:指定日志的打开模式,默认为'a',即在filename存在的时候有效

format:指定日志格式字符串,即指定日志输出时所包括的字段信息以及他们的顺序

datefmt:指定日期/时间格式,该项要在format中包含时间字段%(asctime)时才有效

level:指定日志器的日志级别

stream:指定日志输出目标stream,如sys.stdout、sys.stderr以及网络stream,stream和filename不能同时提供,否则会引发ValueError异常

style:Python 3.2中新添加的配置项,指定format格式字符串的风格,可取值为'%'、'{'和'$',默认为'%'

handlers:Python 3.3中新添加的配置项,该选项如果被指定,它应该是一个创建了多个Handler的可迭代对象,这些handler将会被添加到root logger.需要说明的是:filename、stream和handlers这三个配置项只能有一个存在,不能同时出现2个或3个,否则会引发ValueError异常。

format参数的格式字符串

%(name)s             Logger的名字
%(levelno)s      数字形式的日志级别
%(levelname)s     文本形式的日志级别
%(pathname)s    调用日志输出函数的模块的完整路径名,可能没有
%(filename)s    调用日志输出函数的模块的文件名
%(module)s    调用日志输出函数的模块名
%(funcName)s    调用日志输出函数的函数名
%(lineno)d    调用日志输出函数的语句所在的代码行
%(created)f      当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d    输出日志信息时的,自Logger创建以 来的毫秒数
%(asctime)s          字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d          线程ID。可能没有
%(threadName)s        线程名。可能没有
%(process)d         进程ID。可能没有
%(message)s         用户输出的消息

升级版日志

import logging
LOG_FORMAT = '%(asctime)s %(name)s %(levelname)s %(pathname)s %(message)s' #配置日记的输出格式
DATE_FORMAT = '%Y-%m-%d %H:%M:%S %a' #配置时间输出格式
logging.basicConfig(level=logging.DEBUG,
format=LOG_FORMAT,
datefmt=DATE_FORMAT,
filename=r'C:\Users\Administrator\PycharmProjects\PYL\temp_file\aaa'
)
logging.debug('DEBUG')
logging.info('INFO')
logging.warning('WARNING')
logging.error('ERROR')
logging.critical('CRITICAL')

打印到文件的内容:

2019-09-12  17:12:12 Thu root DEBUG C:/Users/Administrator/PycharmProjects/PYL/temp_file/pyfile.py DEBUG
2019-09-12 17:12:12 Thu root INFO C:/Users/Administrator/PycharmProjects/PYL/temp_file/pyfile.py INFO
2019-09-12 17:12:12 Thu root WARNING C:/Users/Administrator/PycharmProjects/PYL/temp_file/pyfile.py WARNING
2019-09-12 17:12:12 Thu root ERROR C:/Users/Administrator/PycharmProjects/PYL/temp_file/pyfile.py ERROR
2019-09-12 17:12:12 Thu root CRITICAL C:/Users/Administrator/PycharmProjects/PYL/temp_file/pyfile.py CRITICAL

日志器(Logger)是有层级关系的,上面调用的logging模块级别的函数所使用的日志器是RootLogger类的实例,其名称为'root',它是处于日志器层级关系最顶层的日志器,且该实例是以单例模式存在的

如果要记录的日志中包含变量数据,可使用一个格式字符串作为事件的描述消息(logging.debug、logging.info等函数的第一个参数),然后将变量数据作为第二个参数*args的值进行传递

logging.debug('This is the %d %s log.',1,'DEBUG')
2019-09-12  17:35:54 Thu root DEBUG C:/Users/Administrator/PycharmProjects/PYL/temp_file/pyfile.py This is the 1 DEBUG log.

日志流处理流程

logging模块的四大组件

1.日志器 Logger 提供了应用程序可一直使用的接口

2.处理器 Handler 将logger创建的日志记录发送到合适的目的输出

3.过滤器 Filter 提供了更细粒度的控制工具来决定输出哪条日志记录,丢弃哪条日志记录

4.格式器 Formatter 决定日志记录的最终输出格式

组件之间的描述关系

1.logger需要通过handler将日志信息输出到目标位置,如:文件、sys.stdout、网络等

2.不同的logger可以将日志输出到不同位置

3.每个handler都可以设置自己的filter实现日志过滤,从而只保留感兴趣的日志

4.每个handler都可以设置自己的filter实现同一条日志以不同的格式输出到不同的地方

5.logger可以设置多个handler将同一条日志记录输出到不同的位置

即logger是入口,真正干活儿的是handler,handler还可以通过过滤器filter和formatter对要输出的日志内容做过滤和格式化等处理操作

与logging四大组件相关的类:

1.Logger:提供应用程序可直接使用的接口

2.Handler:发送日志到适当的目的地

3.Filter:提供了过滤日志信息的方法

4.Formatter:指定日志显示格式

logging模块学习博客链接:https://www.cnblogs.com/Nicholas0707/p/9021672.html

Python学习日记(二十八) hashlib模块、configparse模块、logging模块的相关教程结束。

《Python学习日记(二十八) hashlib模块、configparse模块、logging模块.doc》

下载本文的Word格式文档,以方便收藏与打印。