zoukankan      html  css  js  c++  java
  • python之路_常用模块补充

    一、摘要算法——hashlib模块

    1、算法介绍

      Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。

      什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。

    2、MD5算法

      MD5是最常见的摘要算法,速度很快,生成结果是固定的128 bit字节,通常用一个32位的16进制字符串表示。另一种常见的摘要算法是SHA1,调用SHA1和调用MD5完全类似,对于相同数据分块进行update(),hexdigest()得出的结果是一样的:

    import hashlib
    md5_obj = hashlib.md5()
    md5_obj.update(bytes('李李',encoding='utf-8'))           #update方法接收字节数据类型
    md5_obj.update(bytes('李李李',encoding='utf-8'))
    md5_obj.update(bytes('杰杰杰杰杰',encoding='utf-8'))
    print(md5_obj.hexdigest())                              #输出结果:2dc701a9f49031673c8f7f9622b7000f
    
    import hashlib
    md5_obj = hashlib.md5()
    md5_obj.update(bytes('李李李李李杰杰杰杰杰',encoding='utf-8'))
    print(md5_obj.hexdigest())                              #输出结果;2dc701a9f49031673c8f7f9622b7000f

    3、MD5算法的应用

    (1)检查文件的一致性:文字文件:逐行读取,视频文件:按字节读

    #检查文字文件
    import hashlib
    md5_obj = hashlib.md5()
    f = open('filename','rb')
    for line in f:
        md5_obj.update(line)
    print(md5_obj.hexdigest())
    #检查视频文件
    import hashlib
    import os
    filesize = os.path.getsize('filename')
    f = open('filename','rb')
    md5_obj = hashlib.md5()
    while filesize > 0 :
        readsize = 10 if filesize>10 else filesize            #每次读取量根据文件大小自己决定
        content = f.read(readsize)
        md5_obj.update(content)
        filesize -= readsize
    print(md5_obj.hexdigest())

    (2)储存密文密码

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

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

      考虑这么个情况,很多用户喜欢用123456,888888,password这些简单的口令,于是,黑客可以事先计算出这些常用口令的MD5值,得到一个反推表:

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

    这样,无需破解,只需要对比数据库的MD5,黑客就获得了使用常用口令的用户账号。对于用户来讲,当然不要使用过于简单的口令。但是,我们能否在程序设计上对简单口令加强保护呢?由于常用口令的MD5值很容易被计算出来,所以,要确保存储的用户口令不是那些已经被计算出来的常用口令的MD5,这一方法通过对原始口令加一个复杂字符串来实现,俗称“加盐”:

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

      经过Salt处理的MD5口令,只要Salt不被黑客知道,即使用户输入简单口令,也很难通过MD5反推明文口令。但是如果有两个用户都使用了相同的简单口令比如123456,在数据库中,将存储两条相同的MD5值,这说明这两个用户的口令是一样的。有没有办法让使用相同口令的用户存储不同的MD5呢?如果假定用户无法修改登录名,就可以通过把登录名作为Salt的一部分来计算MD5,从而实现相同口令的用户也存储不同的MD5。

    import hashlib
    #存储密文密码
    f = open('userinfo','w')
    md5 = hashlib.md5(b'salt')  #加盐处理
    md5.update(b'3714')
    md5_value = md5.hexdigest()
    f.write('alex|%s
    '%md5_value)
    f.close()
    #登录读取验证
    pwd = input('pwd : ')
    f = open('userinfo')
    alex_info = f.readline().strip()
    user,passwd = alex_info.split('|')
    md5 = hashlib.md5(b'salt')  #加盐处理
    md5.update(bytes(pwd,encoding='utf-8'))
    if passwd == md5.hexdigest():
        print('登录成功')

      摘要算法在很多地方都有广泛的应用。要注意摘要算法不是加密算法,不能用于加密(因为无法通过摘要反推明文),只能用于防篡改,但是它的单向计算特性决定了可以在不存储明文口令的情况下验证用户口令。

     二、configparser模块

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

    1、创建文件

    [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)

    2、查找文件内容

    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

    3、增删改操作

    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"))

    三、logging模块

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

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

    1、将日志只写入文件或者屏幕显示情况

    import logging
    logging.basicConfig(
                level
    =logging.DEBUG, #设置日志的默认 format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', #设置日志格式:filename为当前程序的文件名 filename='log.txt', #设置日志写入的文件名,一旦被设置日志将不在屏幕显示 filemode='w' #添加日志的写入模式,可以设置为‘a’模式 ) logging.debug('debug msg') logging.info('info msg') logging.warning('warning message') logging.error('error msg') logging.critical('critical msg')

    2、相关配置参数

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

    3、将日志既在文件中储存又在屏幕显示情况(推荐):

    import logging
    #将获得logger_obj对象封装成一个函数
    def get_logger():
        logger_obj=logging.getLogger()                                                                     #获得一个空logger_obj对象
        fh=logging.FileHandler('log.txt')                                                                  #创建一个文件流,log.txt为日志文件名
        fh.setLevel(logging.WARNING)                                                                       #设置文件默认日志级别
        sh=logging.StreamHandler()                                                                         #创建一个屏幕流
        sh.setLevel(logging.ERROR)                                                                         #设置屏幕默认日志级别
        formater=logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')  #设置日志格式
        fh.setFormatter(formater)                                                                          #为文件流设置日志格式
        sh.setFormatter(formater)                                                                          #为屏幕流设置日志格式
        logger_obj.addHandler(fh)                                                                          #为logger_obj对象添加一个文件流
        logger_obj.addHandler(sh)                                                                          #为logger_obj对象添加一个屏幕流
        return logger_obj                                                                                  #返回一个logger_obj对象
    logger_obj=get_logger()
    logger_obj.debug('debug')
    logger_obj.info('info')
    logger_obj.warning('warning')
    logger_obj.error('error')
    logger_obj.critical('critical')

      logging库提供了多个组件:Logger、Handler、Filter、Formatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。另外,可以通过:logger.setLevel(logging.Debug)设置级别,当然,也可以通过fh.setLevel(logging.Debug)单对文件流设置某个级别。

  • 相关阅读:
    19_05_01校内训练[划分]
    19_05_01校内训练[polygon]
    [Untiy]贪吃蛇大作战(四)——游戏主界面
    [Untiy]贪吃蛇大作战(三)——商店界面
    [Untiy]贪吃蛇大作战(二)——规则界面
    [Untiy]贪吃蛇大作战(一)——开始界面
    [C#]简单的理解委托和事件
    [C#]关于override和new在重写方法时的区别
    [C#]关于逆变与协变的基本概念和修饰符in与out的意义
    [剑指Offer]剪绳子
  • 原文地址:https://www.cnblogs.com/seven-007/p/7581751.html
Copyright © 2011-2022 走看看