Python经常使用模块2

一:hashlib模块python

算法介绍:算法

Python摘要算法提供常见的md5和sha1算法数据库

摘要算法又叫哈希算法和散列算法。他经过函数把任意类型数据转换成固定长度的字符串(一般是16进制表示)windows

摘要算法就是经过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。安全

注意:****网络

摘要算法之因此能指出数据是否被篡改过,就是由于摘要函数是一个单向函数,计算f(data)很容易,但经过digest反推data却很是困难。并且,对原始数据作一个bit的修改,都会致使计算出的摘要彻底不一样。运维

***********函数

咱们以常见的摘要算法MD5为例,计算出一个字符串的MD5值:测试

import hashlib
#实例化对象名能够不是md5,能够是其余的如md5_obj
md5=hashlib.md5()
#对函数f()进行实例化
md5.update(b'how to use md5 in python hashlib?')
#导入任意长度的数据,必定是bytes类型
print(md5.hexdigest())
#计算MD5的hexdigest

注意两点:第一:实例化对象名能够是任意    第二:传入数据必须是bytes类型,第三:不能再元字符串加空格等,或作其余修改。网站

若是字符串长度过长,能够不能够分两次计算?

import hashlib
md5=hashlib.md5()
md5.update(b'how to use md5')
md5.update(b'in python hashlib?')
print(md5.hexdigest())

两次打印结果为:

953c047ffa5aad0804aa9dd743ce76c3
953c047ffa5aad0804aa9dd743ce76c3

*********MD5优点:速度快,长度固定***********

MD5是最多见的摘要算法,速度很快,生成结果是固定的128 bit字节,一般用一个32位的16进制字符串表示。另外一种常见的摘要算法是SHA1,调用SHA1和调用MD5彻底相似:

import hashlib
md5=hashlib.sha1()
md5.update(b'how to use md5')
md5.update(b'in python hashlib?')
print(md5.hexdigest())

************SHA1优点:安全,hash值长,可是费时间***************

SHA1的结果是160 bit字节,一般用一个40位的16进制字符串表示。比SHA1更安全的算法是SHA256和SHA512,不过越安全的算法越慢,并且摘要长度更长。

 

摘要算法应用

任何容许用户登陆的网站都会存储用户登陆的用户名和口令。如何存储用户名和口令呢?方法是存到数据库表中:

name    | password
--------+----------
michael | 123456
bob     | abc999
alice   | alice2008

若是以明文保存用户口令,若是数据库泄露,全部用户的口令就落入黑客的手里。此外,网站运维人员是能够访问数据库的,也就是能获取到全部用户的口令。正确的保存口令的方式是不存储用户的明文口令,而是存储用户口令的摘要,好比MD5:

ername | password
---------+---------------------------------
michael  | e10adc3949ba59abbe56e057f20f883e
bob      | 878ef96e86145580c38c87f0410ad153
alice    | 99b1c2188db85afee403b1536010c2c9

考虑这么个状况,不少用户喜欢用123456,888888,password这些简单的口令,因而,黑客能够事先计算出这些经常使用口令的MD5值,获得一个反推表:

'e10adc3949ba59abbe56e057f20f883e': '123456'
'21218cca77804d2ba1922c33e0151105': '888888'
'5f4dcc3b5aa765d61d8327deb882cf99': 'password'

这样,无需破解,只须要对比数据库的MD5,黑客就得到了使用经常使用口令的用户帐号。

对于用户来说,固然不要使用过于简单的口令。可是,咱们可否在程序设计上对简单口令增强保护呢?

因为经常使用口令的MD5值很容易被计算出来,因此,要确保存储的用户口令不是那些已经被计算出来的经常使用口

通过Salt处理的MD5口令,只要Salt不被黑客知道,即便用户输入简单口令,也很难经过MD5反推明文口令。

hashlib.md5("salt".encode("utf8"))

可是若是有两个用户都使用了相同的简单口令好比123456,在数据库中,将存储两条相同的MD5值,这说明这两个用户的口令是同样的。有没有办法让使用相同口令的用户存储不一样的MD5呢?

若是假定用户没法修改登陆名,就能够经过把登陆名做为Salt的一部分来计算MD5,从而实现相同口令的用户也存储不一样的MD5。

摘要算法在不少地方都有普遍的应用。要注意摘要算法不是加密算法,不能用于加密(由于没法经过摘要反推明文),只能用于防篡改,可是它的单向计算特性决定了能够在不存储明文口令的状况下验证用户口令。

 

2: configparser模块

该模块适用于配置文件的格式与windowsini文件相似,能够包含一个或多个节(section),每一个节能够有多个参数(键 = 值)。
建立文件
来看一个好多软件的常见文档格式以下:
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes

[bitbucket.org]
User = hg

[topsecret.server.com]
Port = 50022
ForwardX11 = no
若是想用python生成一个这样的文档怎么作呢?

import configparser  #导入模块

config = configparser.ConfigParser()   #实例化

config["DEFAULT"] = {'ServerAliveInterval': '45',  *键与值一一对应
#实例化对象取值        'Compression': 'yes',
                     'CompressionLevel': '9',
                     'ForwardX11': 'yes'
                     }

config['bitbucket.org'] = {'User': 'hg'}  #修改键值

config['topsecret.server.com'] = {'Host Port': '50022', 'ForwardX11': 'no'}  

with open('example.ini', 'w') as configfile:   #打开文件 以写的方式
    config.write(configfile)        #写入文件句柄

如何查??

查找文件


import configparser

config = configparser.ConfigParser()

# ---------------------------查找文件内容,基于字典的形式

print(config.sections())  # []

config.read('example.ini')

print(config.sections())  # ['bitbucket.org', 'topsecret.server.com']

print('bytebong.com' in config)  # False
print('bitbucket.org' in config)  # True

print(config['bitbucket.org']["user"])  # hg

print(config['DEFAULT']['Compression'])  # yes

print(config['topsecret.server.com']['ForwardX11'])  # no

print(config['bitbucket.org'])  # <Section: bitbucket.org>

for key in config['bitbucket.org']:  # 注意,有default会默认default的键
    print(key)

print(config.options('bitbucket.org'))  # 同for循环,找到'bitbucket.org'下全部键

print(config.items('bitbucket.org'))  # 找到'bitbucket.org'下全部键值对

print(config.get('bitbucket.org', 'compression'))  # yes       get方法Section下的key对应的value

增删改呢:

增删改操做


import configparser

config = configparser.ConfigParser()

config.read('example.ini')

config.add_section('yuan')   增长

config.remove_section('bitbucket.org')   #删除
config.remove_option('topsecret.server.com', "forwardx11")

config.set('topsecret.server.com', 'k1', '11111') 修改
config.set('yuan', 'k2', '22222')

config.write(open('new2.ini', "w"))  写入

3 logging模块(跟日志打交道的模块)

import logging
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')

*******

注意:导入模块的时候logoing.Ddbug()  必须小写,传参数,不能大写

*******

# 默认状况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志
# 这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG)
# 默认的日志格式为日志级别:Logger名称:用户输出消息。

那么如何 灵活配置日志级别,日志格式,输出位置????

mport logging

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S',
                    filename='/tmp/test.log',
                    filemode='w')

logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')

注意:设置等级时候:level=logging.DEBUG

logging.basicConfig()函数中可经过具体参数来更改logging模块默认行为,可用参数有:

filename:用指定的文件名建立FiledHandler,这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式。
level:设置rootlogger(后边会讲解具体概念)的日志级别
stream:用指定的stream建立StreamHandler。能够指定输出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。

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

logger对象配置:

import logging

logger = logging.getLogger()
# 建立一个handler,用于写入日志文件
fh = logging.FileHandler('test.log',encoding='utf-8')

# 再建立一个handler,用于输出到控制台
ch = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

fh.setLevel(logging.DEBUG)

fh.setFormatter(formatter)
ch.setFormatter(formatter)

logger.addHandler(fh) #logger对象能够添加多个fh和ch对象
logger.addHandler(ch)

logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')

 

小结:

logging模块:

# logging
# 操做日志的模块
# 什么叫日志
    # 给用户看的
        # 用户的重要行为
            # 登陆 涉及安全
            # 帐单 钱
    # 给开发和运维和测试人员看的
        # 自测   logging.debug('一些中间结果')
        # 测试   1++++++1
        # 运维
    # 记录
        # 打印在屏幕上
        # 写入文件里
    # logging的优点
        # 格式更加规范
        # 等级更加鲜明

# 简单的配置用法
# import logging
# logging.basicConfig(level=logging.ERROR,  #
#                     format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
#                     datefmt='%a, %d %b %Y %H:%M:%S',
#                     filename='test.log',
#                     filemode='a')
# logging.debug('debug message')  # 调试
# logging.info('info message')    # 信息
# logging.warning('warning message')  # 警告
# logging.error('error message')      # 错误
# logging.critical('critical message')  # 严重错误

# 使用logger对象的用法
import logging
# 首先建立一个logger对象
logger = logging.getLogger()

#建立一个格式
fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# 建立一个 文件句柄 控制向哪一个文件中输出 用什么格式
fh = logging.FileHandler('test3.log',encoding='utf-8')
fh.setFormatter(fmt)

# 建立一个 屏幕句柄 控制向屏幕输出 用什么格式
sh = logging.StreamHandler()
sh.setFormatter(fmt)

# 将logger对象和文件句柄,屏幕句柄绑在一块儿
logger.addHandler(fh)
logger.addHandler(sh)
logger.setLevel(logging.DEBUG)     # 首先必需要总体对logger进行设置
sh.setLevel(logging.INFO)
fh.setLevel(logging.WARNING)
logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')

hashlib模块小结:

# 摘要算法
# a = alex3714   ===摘要==>   174692740812ab238919
# alex3714   ===摘要==> 174692740812ab238919

# 登陆  md5  sha
    # 密码不能使用明文存储
    # 密文存储 摘要算法
# 校验文件一致性   md5
    # 网络的上传下载
    # 保证多台机器状态的一致

import hashlib
# md5_obj = hashlib.md5()
# # md5算法的对象
# md5_obj.update(b'alex3714')  # 使用md5摘要算法对'alex3714'进行摘要
# res = md5_obj.hexdigest()   # 获取摘要以后的结果
# print(res,type(res))  #aee949757a2e698417463d47acac93df    32位

# user = input('user : ')
# passwd = input('passwd : ')
# md5_obj = hashlib.md5()
# md5_obj.update(passwd.encode('utf-8'))
# passwd = md5_obj.hexdigest()
# if user == 'alex' and passwd == 'aee949757a2e698417463d47acac93df':
#     print('登录成功')

# md5_obj = hashlib.sha1()
# # md5算法的对象
# md5_obj.update(b'alex3714')  # 使用md5摘要算法对'alex3714'进行摘要
# res = md5_obj.hexdigest()   # 获取摘要以后的结果
# print(res)  #8a003668a9c990f15148f9e4046e1410781533b6  40

# 相同的字符串使用相同的算法 在任什么时候候 获得的结果都是一致的


# 全世界的md5算法都是同样的
# 123456  111111
# md5_obj = hashlib.md5()
# md5算法的对象
# md5_obj.update(b'123456')  # 使用md5摘要算法对'alex3714'进行摘要
# res = md5_obj.hexdigest()   # 获取摘要以后的结果
# print(res,type(res))  #aee949757a2e698417463d47acac93df    32位
# 123456 e10adc3949ba59abbe56e057f20f883e
# 撞库

# 加盐
# md5_obj = hashlib.md5('盐'.encode('utf-8'))
# # md5算法的对象
# md5_obj.update(b'alex3714')  # 使用md5摘要算法对'alex3714'进行摘要
# res = md5_obj.hexdigest()   # 获取摘要以后的结果
# print(res,type(res))
#aee949757a2e698417463d47acac93df    32位
#0e249b9c16ea1d840ce700587cada978

# 动态加盐  _ 校园管理系统
# username = 'alex'   # alex alex3714
#                     # egon egon5068
# md5_obj = hashlib.md5(username.encode('utf-8')+'盐'.encode('utf-8'))
# md5_obj.update(b'alex3714')
# res = md5_obj.hexdigest()
# print(res)

# 校验文件一致性
# with open('userinfo','rb') as f:
#     md5_obj = hashlib.md5()
#     md5_obj.update(f.read())
#     res = md5_obj.hexdigest()
#     print(res)
#
# with open('userinfo','rb') as f:
#     md5_obj = hashlib.md5()
#     for line in f:
#         md5_obj.update(line)   # update操做能够在hexdigest以前执行屡次
#                                # 分次对一个长字符串进行摘要
#     res = md5_obj.hexdigest()  # 结果是对整个长字符串的摘要结果
#     print(res)

#56fc9aa78c2dd71d547988b24bec198a

# md5_obj = hashlib.md5()
# md5_obj.update(b'aaabbb')
# res = md5_obj.hexdigest()
# print(res)  #6547436690a26a399603a7096e876a2d
#
# md5_obj = hashlib.md5()
# md5_obj.update(b'aa')
# md5_obj.update(b'abbb')
# res = md5_obj.hexdigest()
# print(res)  #6547436690a26a399603a7096e876a2d

 

练习:

# hashlib
    # 给校园管理系统添加密文登陆的功能
    # 检验两个文件的一致性  md5
        # func(文件a的路径,文件b的路径):
            # return TRUR 或者 False

# logging模块
    # 给校园管理系统添加日志
    # 建立 删除 关联 这种关键信息建立日志

# 重写附加题
    # 用堆栈思想
相关文章
相关标签/搜索