学习python课程第二十天

Posted lvyipin1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习python课程第二十天相关的知识,希望对你有一定的参考价值。

一.     logging模块

  1.  日志的级别分别有:

    logging.debug  (‘‘这是一个调试信息‘‘)  #10 级别最低

    logging.info  (‘一些常规的信息‘)  #20

    logging.warning  (‘警告信息‘)  #30

    logging.error  (‘错误信息‘)  #40

    logging.critical  (‘严重错误‘)  #50

 

    #  在logging模块中又对应的常量用来表示级别

     默认情况下  默认级别是#30  waming  日志输出位置是控制台

 

  2.  自定义日志的配置

  示例:

    logging.basicConfig(

      filename = ‘a.log‘

      filemode = ‘at‘

      level = 10,

      format = ‘%(asctime)s  %(levelname)s  %(funcName)s  %(lineno)s  %(message)s‘,

      datefmt = ‘%Y-%m-%d  %X  %p‘)

    logging.debug(‘这是调试信息‘)

 

  可用参数:

    filename : 用指定的文件名创建FiledHandler (后边会具体讲解handler的概念) , 这样日志会被存储到

    指定的文件中

    

    filemode : 文件打开的方式, 在指定了filename时使用这个参数, 默认值为 ‘a‘ 还可以指定为 ‘w‘ .

    

    format  :  指定handler使用的日志显示格式

 

    datefmt  : 指定日期的格式

 

    level : 设置root logger (后边会讲解具体的概念) 的日志级别

 

    stream : 用指定的stream 创建streamHandler . 可以指定输出到sys.stderr , sys.stdout 或者文件

    默认为 sys.stderr, 若同时列出了filename 和 stream两个参数. 则stream参数会被忽略.

 

    可用的格式分别为 :

      %(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:35 ,  897‘.逗号后面是毫秒

      %(therad)d : 线程ID, 可能没有

      %(theradName)s : 线程名 可能没有

      %(process)d: 进程ID, 可能没有

      %(message)s : 用户输出的消息

 

  3. 如何能够同时输出到多个位置 ? 

   logging中的四个核心角色 !!

    1.   logger  生成器

    2.   handler 处理器

    3.   filter      过滤器

    4.   formatter  格式化

    

    一条日志完整的生命周期 : 

    1. 由logger 产生日志 -> 2. 交给过滤器判断是否被过滤 -> 3. 将日志消息分发给绑定的所有处理器. -> 4.

    处理器按照绑定的格式化对象输出日志

    其中, 第一步会先检查日志的级别, 如果低于设置的级别, 则不执行  第四步 如果不指定格式则按照默认格式

 

    1.  创建一个日志生成器 :

    mylog  = logging.getLogger(‘mylog‘)

    # 设置生成器级别

    mylog.setLevel(logging.DEBUG)

 

    2. 创建一个日志处理器 :

    fh = logging.FileHandler(‘b.log‘,encoding=‘utf-8‘)

 

    3. 创建一个格式处理器

    fm = logging.Formatter(

      ‘%(asctime)s %(levelname)s %(funcName)s %(lineno)s %(message)s‘ ,

       datefmt = ‘%Y-%m-%d  %X  %p‘)

  

    4. 将三个对象进行关联

    mylog.addHandler(fh)

    fh.setFormatter(fm)

    #  测试

    mylog.debug(‘mylog 的 测试‘)

 

 

  4.  日志的继承

    可以将一个日志指定为另一个日志的子日志, 或子孙日志, 当存在继承关系时, 子孙级日志收到日志时

    会将该日志向上传递,

    指定继承关系 :

    log1 = logging.getLogger(‘father‘)

    log2 = logging.getLogger(‘father.son‘)

    log3 = logging.getLogger(‘father.son.grandson‘)

 

    # 默认值为True, 表示 有继承关系. 当子的日志产生日志时, 给他父级以及父级以上都发一份.

    如果不需要, 就设置为False

    log3.propagate = False

 

    fh = logging.FileHandler(‘c.log‘.encoding=‘utf-8‘)

 

    fm = logging.Formatter(

      ‘%(asctime)s  %(levelname)s  %(funcName)s  %(lineno)s  %(message)s‘ ,

      datefmt = ‘%Y-%m-%d  %X  %p‘)

 

    log1.addHandler(fh)

    log2.addHandler(fh)

    log3.addHandler(fh)

 

    fh.setFormatter(fm)

    # 测试

    log3.error(‘测试‘)

    #  取消传递

    log3.propagate = False

    

    log1.warning(‘father  log‘)

    log2.warning(‘father.son log‘)

    log3.warning(‘father.son.grandson log‘)  

  

 

  5. 通过字典配置日志模块

     每次都要编写代码来配置,非常麻烦, 我们最好能够写一次到处用.

    logging.config.dictConfig()

 

 

  6. 加载配置 :

    import  logging.config

    logging.config.dictConfig (LOGGING_DIC)

    logging.getLogger(‘aa‘).debug(‘测试‘)

    

    #  getLogger参数就是对应字典中loggers的key  如果没有匹配到key  什么都不做, 很多情况我们的日志

    可能对应不同的业务模块  我们需要在日志中体现业务信息  那问题是, 我的配置中不可能预先知道所有

    的业务名称  这时候我们可以将key设置为空,  这样以来, 获取的时候如果找不到对应的就用默认的. 并且

    日志对象的名称会变成你传入的key

    

  7.  流 处理器

    log1 = logging.getLogger(‘a‘)

    

    #输出文件

    fh = logging.FileHandler(‘c.log‘,encoding=‘utf-8‘)

 

    #输出到控制台

    sh = logging.StreamHandler()

 

    log1.addHandler(sh)

    log1.addHandler(fh)

    fm = logging.Formatter(

      ‘%(asctime)s  %(levelname)s  %(funcName)s  %(lineno)s  %(message)s‘,

      datefmt = ‘%Y-%m-%d  %X  %p‘)

 

    sh.setFormatter(fm)

 

    log1.warning(‘测试2!‘)

 

    import  lib.common

    logger = lib.common.get_logger()

 

    def  login():

      logger.debug(‘测试 测试!‘)

    login()

 

 

  

二.   hashlib模块

 

  1. 什么是hash lib

    hash是一种算法, 是将一个任意长的数据, 根据计算, 得到一个固定长度特征码

    特征: 不同输入, 可能会有相同的结果.  但是几率特别小.

        相同的输入  必然得到相同的结果

        由于散列(特征)的性质  从原理来看是不可能反解的.

 

    用来验证  两个输入的数据是否一致

    使用场景

    1.  密码验证 

             123432      44sdas4kkas4tk

            client 加密后的结果.     server  拿到加密后. 

 

    2.  验证数据是否被篡改过.  比如游戏安装包. 可以对比一下有没有被改过

 

    为了防止别人撞库成功   可以提升密码的复杂度. 其次可以为密码加盐 (加点内容进去)

 

 

    示例:

      import  hashlib

      m  = hashlib.md5(‘aaa.encode(‘utf-8‘)‘)

      print (len(m.hexdigest()))

 

      # 撞库破解的原理.  有人事先把常见的明文和密文的对应关系存到了数据库中.

        运气好就能查到

      # 可以选择密文的长度,

      h1 = hashlib.sha512(‘123‘.encode(‘utf-8‘))

      print(h1.hexdigest())

 

    加盐:

      m = hashlib.md5(‘321‘.encode(‘utf-8‘))

      # 加

      m.update(‘asfasfafasf‘.encode(‘utf-8‘))

      print (m.hexdigest())

 

    在创建的时候必须加盐的类型

      import  hmac

      h = hmac.new(‘asdad‘.encode(‘utf-8‘))

      h.update(‘123‘.encode(‘utf-8‘))

      print(h.hexdigest())

 

 

三.   re 模块

  re是Regular Expression 的简称, 表示正则表达法

    什么是正则表达式 ?

    表达式指的是默写带有特殊含义的符号或者符号组成的式子

    正则表达式是对字符进行处理的逻辑公式, 使用特殊字符或者一些特殊字符的组合,

    组成一个规则字符串, 这个规则字符串用来表达对字符的过滤逻辑

    支持的字符及其表达的含义.

 

  re 的使用:

    在爬虫里大量的使用  其实有框架帮你封装了这些复杂的正则

    在网站和手机app的注册功能中大量使用, 例如判断你的邮箱地址是否正确,

 

  1. 普通匹配.

    s  w  d      .

 

  2. 重复匹配.

    *:  任意,     +:1-  无穷      ?:0 - 1

 

  3. 范围匹配

    a|b|c  [abc]  [0-9] [a-z] [A-Z]  [0-9a - zA - Z]  注意: 仅匹配一个字符. 它的范围是根据ascii码表

 

    

    print(re.findall("w","1aA_*")) # 匹配数字字母下划线
   
    print(re.findall("W","1aA_*,")) # 匹配非数字字母下划线
    
    print(re.findall("s"," f")) # 匹配任意空白字符
    
    print(re.findall("S"," f")) # 匹配任意非空白字符
    
    print(re.findall("d","123abc1*")) # 匹配任意非空白字符
    
    print(re.findall("D","123abc1*")) # 匹配任意非空白字符
    
    print(re.findall("[abc]","AaBbCc")) # 匹配 a b c都行
    
    print(re.findall("[^abc]","AaBbCc")) # 除了 a b c都行
    
    print(re.findall("[0-9]","AaBbCc12349")) # 除了 a b c都行
    
    print(re.findall("[a-z]","AaBbCc12349")) # a-z 英文字母
    
    print(re.findall("[A-z]","AaBbC:c??2349[]")) # A-z 匹配原理 是按照ascII码表


4.匹配位置

    print(re.findall("Ad","123abc1*")) # 从字符串的开始处匹配
    
    
print(re.findall("d","123abc1*9 ")) # 从字符串的结束处匹配 注意把写在表达式的右边
    
    print(re.findall("d$","123abc1*9")) # 从字符串的结束处匹配 如果末尾有换行 换行不会参与匹配
    
    
    print(re.findall("^d","s1asasas121 ")) # 从字符开始匹配数字


 

 

  

 


































以上是关于学习python课程第二十天的主要内容,如果未能解决你的问题,请参考以下文章

Linux课程第二十天学习笔记

学习Python的第二十天三级菜单高级版

第二十天 PYTHON学习

python学习第二十天

2018.10.16python学习第二十天

python学习第二十天文件操作方法