第22天 常用模块三

介绍的模块

logginghashlib

 模块一:logging

人生三问

什么是日志  对每天所发生的事情做的记录就是日志。
为什么要用日志  日志记录了我们程序每天发生了什么事情,这个对于我们程序的维护有很大的帮助。例如每天都会有同一个ip在尝试登陆我们的网站,如果我们没有日志就不会知道有这样一个现象发生,可能在多年之后程序就会被攻破,但是如果有了日志,我们就能即使的发现程序的异常,并及时的修复它。
怎么使用日志?预备知识:日志级别  1. debug  日常的调试信息  数字表示code为10  2. info   常规信息  code为20  3. warning  提醒信息  code为30  4. error  错误信息  code为40  5. critical  常规的错误信息  code为50系统默认的级别是30

系统默认级别为warning,并打印到终端中:

# 错误信息
logging.debug(‘调试信息‘)
logging.info(‘常规信息‘)
logging.warning(‘提醒信息‘)
logging.error(‘错误信息‘)
logging.critical(‘重大错误信息‘)

# 结果:
# WARNING:root:提醒信息
# ERROR:root:错误信息
# CRITICAL:root:重大错误信息

日志的基础配置信息

import logging
# 配置日志格式的时候无法通过basicConfig来配置编码方式
format = ‘%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s‘
logging.basicConfig(
    filename=‘d.log‘, # 日志的输出的文件,不写默认是终端
    filemode=‘a‘, # 这个是打开文件的格式,默认是追加写入
    level=logging.DEBUG, # 日志的显示级别,默认是warning以上
    datefmt=‘%Y‘, # 显示日期的格式,和format配套使用
    format=format  # 显示日志的格式
    # stream:用指定的stream创建StreamHandler。
    # 可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。
    # 若同时列出了filename和stream两个参数,则stream参数会被忽略。
)
logging.debug(‘这是一个调试信息!‘)

# 打开文件d.log,发现有乱码

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用户输出的消息

format参数中可能用到的格式化串

日志系统的四个核心组件

1. logger 日志生成器
2. filter 日志过滤器
3. handler 日志处理器,主要是用来调用formatter控制打印输出4. formatter 日志格式定义

创建一个自己的日志生成器:

import logging
# 1. 创建一个日志生成器
my_logger = logging.getLogger(‘my_logger‘)
# 1.1 设置日志生成器的级别
my_logger.setLevel(logging.DEBUG)
# 2. 创建一个日志处理器, 此处可以设置编码方式
my_handler = logging.FileHandler(‘f.log‘, ‘a‘, encoding=‘utf-8‘)
# 3. 创建一个日志格式定义
my_formatter = logging.Formatter(format)
# 4. 关联生成器处理器
my_logger.addHandler(my_handler)
# 5. 关联处理器和格式定义
my_handler.setFormatter(my_formatter)

my_logger.debug(‘这是一个debug信息!‘)# 文件信息:
2018-10-18 15:26:37,668 - my_logger - DEBUG -log模块练习:  这是一个debug信息!

日志的继承:

import logging
# 创建三个日志生成器
log1 = logging.getLogger(‘father‘)
log2 = logging.getLogger(‘father.son‘)
log3 = logging.getLogger(‘father.son.chiren‘)

# 创建日志处理器
log1_handler = logging.FileHandler(‘g.log‘, ‘a‘, encoding=‘utf-8‘)
# log2_handler = logging.FileHandler(‘g.log‘, ‘a‘, encoding=‘utf-8‘)
# log3_handler = logging.FileHandler(‘g.log‘, ‘a‘, encoding=‘utf-8‘)

# 创建一个formatter
format1 = ‘%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s‘
log_format = logging.Formatter(format1)

# 关联生成器,处理器和定义格式
log1.addHandler(log1_handler)
log2.addHandler(log1_handler)
log3.addHandler(log1_handler)

log1_handler.setFormatter(log_format)

# 生成日志
# log1.debug(‘father_log‘)  # 此时是创建了g.log文件,但是文件是空的,因为默认的级别是warning
# log1.warning(‘father_log‘) # 此时文件内容:2018-10-18 18:15:09,940 - father - WARNING -log模块练习:  father_log

# log2.warning(‘father.son.log‘)
# 此时文件内容为:因为此时father继承了son的日志
# 2018-10-18 18:15:09,940 - father - WARNING -log模块练习:  father_log
# 2018-10-18 18:16:20,146 - father.son - WARNING -log模块练习:  father.son.log
# 2018-10-18 18:16:20,146 - father.son - WARNING -log模块练习:  father.son.log

log3.warning(‘father.son.chiren.log‘)
# 此时文件内容又增加了三条,因为此时继承log3日志有两个父级
# 2018-10-18 18:15:09,940 - father - WARNING -log模块练习:  father_log
# 2018-10-18 18:16:20,146 - father.son - WARNING -log模块练习:  father.son.log
# 2018-10-18 18:16:20,146 - father.son - WARNING -log模块练习:  father.son.log
# 2018-10-18 18:18:32,956 - father.son.chiren - WARNING -log模块练习:  father.son.chiren.log
# 2018-10-18 18:18:32,956 - father.son.chiren - WARNING -log模块练习:  father.son.chiren.log
# 2018-10-18 18:18:32,956 - father.son.chiren - WARNING -log模块练习:  father.son.chiren.log

练习: 创建一个日志生成器,让日志可以以三种不同的格式写入文件和打印到终端中

import logging
# 创建一个日志生成器
logger = logging.getLogger(__file__)

# 创建三个不同的处理器打印到终端和文件中
logger_handler1 = logging.FileHandler(‘ceshi1.log‘, encoding=‘utf-8‘)
logger_handler2 = logging.FileHandler(‘ceshi2.log‘, encoding=‘utf-8‘)  # 日志输出到两个文件中
logger_handler3 = logging.StreamHandler()  # 打印到终端

# 创建三种格式,格式对应
logger_format1 = logging.Formatter(
    ‘%(asctime)s - %(name)s - %(funcName)s - %(module)s - %(message)s‘,
    datefmt=‘%Y-%m-%d %X %p‘
)
logger_format2 = logging.Formatter(
    ‘%(asctime)s - %(name)s - %(funcName)s - %(module)s - %(lineno)s - %(message)s‘,
    datefmt=‘%Y-%m-%d %X %p‘
)
logger_format3 = logging.Formatter(‘%(module)s - %(message)s ‘)

# 处理器关联定义格式
logger_handler1.setFormatter(logger_format1)
logger_handler2.setFormatter(logger_format2)
logger_handler3.setFormatter(logger_format3)

# 设置日志级别
logger.setLevel(logging.DEBUG)
# 添加处理器
logger.addHandler(logger_handler1)
logger.addHandler(logger_handler2)
logger.addHandler(logger_handler3)

# 输出日志
logger.debug(‘这是一个debug信息! ‘)

# 输出信息:
‘‘‘
终端:log模块练习 - 这是一个debug信息!
ceshi1.log文件:2018-10-18 18:36:19 PM - H:/python_study/day22/log模块练习.py - <module> - log模块练习 - 这是一个debug信息!
ceshi2.log文件:2018-10-18 18:36:19 PM - H:/python_study/day22/log模块练习.py - <module> - log模块练习 - 95 - 这是一个debug信息! 

‘‘‘

测试代码

案例分享:

通过logging读出来日志配置文件并可以使用

创建规范化目录的小工具:

import os, sys

dir_list = [‘conf‘, ‘core‘, ‘bin‘, ‘lib‘, ‘db‘, ‘log‘]

def create_dir(parent_path, dir_list):
    ‘‘‘
    在一个目录下面创建规范目录
    :param parent_path: 需要创建的文件夹, 是全局路径
    :param dir_list: 创建的规范目录列表
    :return: 创建成功返回True
    ‘‘‘
    # 先规范化目录
    parent_path = os.path.normpath(parent_path)
    # 循环列表拼接目录并且创建
    for dir in dir_list:
        # 当前需要创建的目录路径
        current_dir = os.path.join(parent_path, dir)
        # 路径不存在则创建目录
        if not os.path.exists(current_dir):
            os.mkdir(current_dir)

if os.path.isdir(sys.argv[1]):
    create_dir(sys.argv[1], dir_list)
else:
    print(‘Usag: python current_exec_file parent_dir_path!‘)

在一个目录下面创建规范目录

初始化操作: 创建规范目录,并创建logging配置文件

文件内容:

# star.py文件内容

# 添加环境变量
import sys, os

BASE_DIR = os.path.normpath(os.path.join(
    __file__,
    os.pardir,
    os.pardir
))

sys.path.append(BASE_DIR)

# 导入核心逻辑代码程序并运行
import core.atm
import core.shop
core.atm.login()
core.shop.register()

# atm.py文件内容
def login():
    print(‘loggin‘)
# shop.py文件内容
def register():
    print(‘register‘)

文件内容

问题1:此时执行核心代码的login和register都是可以正常运行的,但是当他们执行的时候我想去往日志文件中写入日志,但是我又不想每次通过上面的方式手动的创建一个日志生成器,然后配置一些内容。说白了就是想把日志信息保存到配置文件中,每次想用的时候调用一下就可以了,因此写入配置文件settings的内容如下:

日志字典的解析

import os, sys
STANDARD_FORMAT = ‘%(asctime)s %(name)s %(funcName)s %(module)s %(message)s‘
SIMPLE_FORMAT = ‘%(asctime)s %(module)s %(message)s‘
COMPLETE_FORMAT = ‘%(asctime)s %(name)s %(funcName)s %(lineon)s %(module)s %(message)s‘

# 拼接日志文件存储路径
LOGFILE_PATH = os.path.normpath(os.path.join(
    __file__,
    os.pardir,
    os.pardir,
    ‘log‘,
    ‘a.log‘))

print(LOGFILE_PATH)

# 这个就是之前通过手工的方式创建的四个日志核心组件
LOGGING_DIC = {
    # 日志字典的版本,这个自己设置的
    ‘version‘: 1,
    # 日志格式定义字段,通过一定格式的字符串进行创建
    ‘formatters‘: {
        # 定义了日志的表示格式标准格式,简单格式和完整格式
        ‘standard‘: {
            ‘format‘: STANDARD_FORMAT
        },
        # 简单格式
        ‘simple‘: {
            ‘format‘: SIMPLE_FORMAT
        },
        # 完整格式
        "complete":{
            "format": COMPLETE_FORMAT
        }
    },
    # 日志过滤器,暂时设置成空
    ‘filters‘: {},
    # 日志处理器
    ‘handlers‘: {
        # 定义了两种日志处理器
        # 把日志内容打印到终端
        ‘console‘: {
            ‘level‘: ‘DEBUG‘,  # 日志级别
            ‘class‘: ‘logging.StreamHandler‘,  # 日志流处理器
            ‘formatter‘: ‘simple‘   # 使用的打印格式是上面设置的simple
        },
        ‘default‘: {
            ‘level‘: ‘DEBUG‘,
            ‘class‘: ‘logging.handlers.RotatingFileHandler‘,   # 设置文件通过一定大小之后就换文件
            ‘formatter‘: ‘standard‘,  # 写入文件的格式是上面定义的标准格式
            ‘filename‘: LOGFILE_PATH,  # 写入文件的路径
            ‘maxBytes‘: 1024 * 1024 * 5,  # 日志文件的最大大小为5M 超出后 换文件
            ‘backupCount‘: 5, # 最多留五个日志文件
            ‘encoding‘: ‘utf-8‘, # 写入的时候编码方式
        },
    },
    # 日志生成器
    ‘loggers‘: {
        # 在getLogger的时候  如果指定的名称 不存在 或者不给名称 用的就是默认的
        # 在这里如果key为空 它就是默认的
        # 你可以自己定义生成器的名称 并且他们还能使用相同的默认配置
        ‘‘: {
            ‘handlers‘: [‘default‘, ‘console‘],
            ‘level‘: ‘DEBUG‘,
            ‘propagate‘: False,
        },
    },
}

日志配置字典

问题2:日志文件配置完成之后,首先我们应该考虑的时候日志生成器应该放在哪个文件里面,atm或者shop核心代码在运行的时候都是要进行记录日志的,因此我们应该把日志生成器函数写在一个公共组件里面以便于后续的调用,但是我们应该怎么去创建一个日志生成器呢?首先在common里面写入我们的日志生成器代码

# 导入日志模块和配置文件
import logging.config
import conf.settings

def create_logger():
    # 将配置文件导入到logging中
    logging.config.dictConfig(config=conf.settings.LOGGING_DIC)
    # 根据配置文件获得一个关联了日志处理器和格式的生成器
    logger = logging.getLogger(‘loggers‘)
    logger.debug(‘这是一个debug文件‘)

配置atm.py文件为下:

# 导入日志模块
import lib.common

def login():
    print(‘loggin‘)
    # 当函数执行完成之后写入日志
    lib.common.create_logger()

执行start文件之后发现

终端中输出:
2018-10-18 19:54:25,557 common 这是一个debug文件
log目录下创建了一个文件内容为:
2018-10-18 19:54:25,557 loggers create_logger common 这是一个debug文件

问题3:此时我们的日志模块基本上是已经创建完成了,但是还有一些小小的问题,就是我们希望的是可以在函数内自定义输入日志的内容,而不是由公共组件给我们定义输入的内容。也就是说我们的公共组件create_logger应该给我们返回一个日志生成器,然后在函数中获得此生成器,往文件中写入我们想要的内容。

修改common.py文件如下:

# 导入日志模块和配置文件
import logging.config
import conf.settings

def create_logger():
    # 将配置文件导入到logging中
    logging.config.dictConfig(config=conf.settings.LOGGING_DIC)
    # 根据配置文件获得一个关联了日志处理器和格式的生成器
    return logging.getLogger(‘loggers‘)

修改atm.py文件内容如下:

# 导入日志模块
import lib.common

def login():
    print(‘loggin‘)
    # 当函数执行完成之后写入日志
    lib.common.create_logger().debug(‘今天我登陆了atm取款机!‘)

重新执行start.py文件发现没有问题,至此我们通过配置文件创建日志格式的内容就算大功告成了!

模块二:hashlib

 人生三问

什么是hash  hash是一种将任意长度的数据经过计算返回固定长度特征码的算法。
为什么要用hash  1. 无论值多大,hash值都是一样长度的  2. 同一个值hash值是一样的, 不同的值hash是不一样的  3. 不会被反解  基于上述特点,我们可以使用hash对数据进行完整性校验。
怎么使用hashlib  hashlib封装了一系列的哈希算法,我们可以通过hexdigest得到相应的的散列值

注意的是:hash算法只能计算字节,也就是说传入的值必须是字节类型的。

使用方法:

# 把一段很长的数据update多次与一次update这段数据是一样的
import hashlib
# 一段很长的数据helloalvin
m2 = hashlib.md5()
m2.update(‘helloalvin‘.encode(‘utf-8‘))
print(m2.hexdigest())  # 92a7e713c30abbb0319fa07da2a5c4af

# 直接当参数传递进去也是一样的
m3 = hashlib.md5(‘helloalvin‘.encode(‘utf-8‘))
print(m3.hexdigest())  # 92a7e713c30abbb0319fa07da2a5c4af

# 拆分开之后计算hash值
m = hashlib.md5()
print(m.hexdigest()) # d41d8cd98f00b204e9800998ecf8427e

m.update(‘hello‘.encode(‘utf-8‘)) # 5d41402abc4b2a76b9719d911017c592
print(m.hexdigest())

m.update(‘alvin‘.encode(‘utf-8‘))  # 92a7e713c30abbb0319fa07da2a5c4af
print(m.hexdigest())

问题:撞库

撞库  因为散列计算的其中一个特点是一样的值通过一样的方法得到的值一定是一样的,也就是说密码123的散列值一定是202cb962ac59075b964b07152d234b70这样子如果有人事先存储了值这一对值,当出现这个散列值的时候我们就会知道你使用的密码是123。  但是库也是有限的,也是大部分经常出现的数据,因此我们只要把密码设置的相对复杂一点,反解是肯定反解不出来的。

模拟撞库:

# 模拟撞库
import hashlib
# 密码
password = [
    ‘hello‘,
    ‘alexhello‘,
    ‘egonhello‘,
    ‘nihaohello‘,
    ‘hello,world‘,
]

def create_password_dict(password):
    temp_dict = {}
    for password_item in password:
        # 计算密码的md5校验值
        hash = hashlib.md5(password_item.encode(‘utf-8‘))
        temp_dict[hash.hexdigest()] = password_item
    # 返回一个密码与password的一个字典库
    print(temp_dict)
    return temp_dict

def pojie_password(hash, password_dict):
    # 如果密码库中存在则返回密码
    if hash in password_dict:
        return password_dict[hash]

# 得到密码库
password_lib = create_password_dict(password)
# 获得密码
ps = pojie_password(‘5d41402abc4b2a76b9719d911017c592‘, password_lib)
if ps:
    print(‘密码为===》%s‘ % ps)
else:
    print(‘密码库中暂时还没有,请稍等!‘)

撞库的实现

另一个加密模块:hmac必须要加盐

import hmac
# 这个里面传入的值是秘钥
h = hmac.new(‘miyao‘.encode(‘utf-8‘))
# 这个是密码
h.update(‘henchangdemima‘.encode(‘utf-8‘))
print(h.hexdigest())   # c3ffabf0cf7eef648ba783c9673a54d1

# 拆分密码
# 密码不能改变,否则出来的结果不一样
h1 = hmac.new(‘miyao‘.encode(‘utf-8‘))

h1.update(‘henchang‘.encode(‘utf-8‘))
h1.update(‘de‘.encode(‘utf-8‘))
h1.update(‘mima‘.encode(‘utf-8‘))

print(h1.hexdigest())  # c3ffabf0cf7eef648ba783c9673a54d1

hmac

原文地址:https://www.cnblogs.com/huwentao/p/9808743.html

时间: 2024-11-14 12:41:51

第22天 常用模块三的相关文章

python全栈开发【第十一篇】Python常用模块三(hashlib,configparser,logging)

hashlib模块 hashlib提供了常见的摘要算法,如md5和sha1等等. 那么什么是摘要算法呢?摘要算法又称为哈希算法.散列算法.它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示). 注意:摘要算法不是一个解密算法.(摘要算法,检测一个字符串是否发生了变化) 应涂:1.做文件校验 2.登录密码 密码不能解密,但可以撞库,用'加盐'的方法就可以解决撞库的问题.所有以后设置密码的时候要设置的复杂一点. #用户密码 import hashlib # md5

常用模块(三)——shelve、xml、hashlib、configparser

常用模块(三) 一.shelve模块 1.shelve模块也是一种序列化模块,内部使用的是pickle模块,所以也存在跨平台性差的问题 2.特点: 只要提供一个文件名即可 读写的方式和字典一样 将数据以类似字典的形式在文件中读写 3.应用场景 在单击的程序中使用 4.使用方法 (1)序列化 1 import shelve 2 3 s1= shelve.open('a.txt') # 打开文件 4 s1['week']=["Sun", "Mon", "Tue

Python学习 :常用模块(三)

常用模块(三) 七.logging模块 日志中包含的信息应有正常的程序访问日志,还可能有错误.警告等信息输出 python的 logging 模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging 的日志可以分为 debug() , info() , warning() , error() , critical() 5个级别 Eg.简单的日志记录 import logging logging.debug('debug message') logging.info('info m

Python 22 常用模块03

常用模块03 re 1. 正则表达式 正则表达式是对字符串操作的各种逻辑公式. 我们一般使用正则表达式对字符串进行匹配和过滤 字符组 字符组很简单用[]括起来. 在[]中出现的内容会被匹配. 例如:[abc] 匹配a或b或c 如果字符组中的内容过多还可以使用- , 例如: [a-z] 匹配a到z之间的所有字母 [0-9] 匹配所有阿拉伯数字 简单元字符 基本的元字符: . 匹配除换行符以外的任意字符 \w 匹配字母或数字或下划线 \s 匹配任意的空字 \d 匹配数字 \n 匹配一个换行符 \t

常用模块

1.import讲解#本质就是.py 文件,用来从逻辑上组织pyhton代码(变量.函数.类.逻辑,实现一个功能) 1.1.导入方法导入多个模块,以逗号隔开 例如 module模块: name = "kangkang" def fun(num): print("num",num) 1) import module print(module.name) #调用模块下的参数 module.fun(23) #调用模块下的方法 结果为: kangkang num 23 2)

python——常用模块

time.asctime(time.localtime(1234324422)) python--常用模块 1 什么是模块: 模块就是py文件 2 import time #导入时间模块 在Python中,通常有这三种方式来表示时间:时间戳.元组(struct_time).格式化的时间字符串: (1)时间戳(timestamp) :通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量.我们运行"type(time.time())",返回的是float类型.

python常用模块(1):collections模块和re模块(正则表达式详解)

从今天开始我们就要开始学习python的模块,今天先介绍两个常用模块collections和re模块.还有非常重要的正则表达式,今天学习的正则表达式需要记忆的东西非常多,希望大家可以认真记忆.按常理来说我们应该先解释模块概念性东西再来学习具体的模块使用.可是直接解释可能反而不好理解,模块的使用非常方便,所以我们采用先介绍使用常用模块过两天再具体进行模块概念的讲解. 预习: 实现能计算类似 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998

python学习第六课 --常用模块

常用模块 sys sys.argv  命令行参数列表,第一个元素是程序本身路径 sys.exit(n)  退出程序,正常退出时exit(0) sys.version sys.maxint  最大的int值 sys.path 返回模块的搜索路径 sys.paltform sys.stdout.wirte("hello") val = sys.stdin.readline()[:-1] logging import logging logging.basicConfig(filename=

Python自动化开发从浅入深-语言基础(常用模块)

模块就是将一些相似功能的代码集中到一起,通过定义形象的模块名称,以便用户查找和使用. 通常模块分为三种:自定义模块,内置标准模块和开源模块. 自定义模块 和开源模块的使用参考 http://www.cnblogs.com/wupeiqi/articles/4963027.html  python中的一些常用模块包括以下几个: 一.time 和 datetime模块: 用于处理时间和日期的. import time import datetime print(time.clock()) #返回处理