• python基础(十七)


    今日主要内容

    • 正则表达式
    • logging模块

    一、正则表达式

    (一)什么是正则表达式

    1. 正则表达式的定义:
      • 是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。
      • 简单来说,我们使用正则表达式就是为了对字符串进行 匹配过滤
    2. 正则表达式的特点:
      • 灵活性强、逻辑性强、功能性强
      • 可以迅速的用极简单的方式控制复杂的字符串

    (二)正则表达式的构成

    • 正则表达式由普通字符元字符构成
      • 普通字符
      • 元字符
    1. 普通字符

      • 普通字符包括:大小写字母、数字,在匹配普通字符的时候直接写就可以了,Python也能实现同样的效果,很简单

        • 利用re模块,返回正则表达式匹配过滤出来的字符
        import re
        
        s = "zxdnbzxdnb"
        print(re.findall("zxd", s))  # 普通字符,直接写就好了
        
        运行结果:
        ['zxd', 'zxd']  # 成功匹配过滤
        
        • Python基础逻辑也可以实现
        s = "zxdnbzxdnb"
        
        print("zxd" in s)  # 是否存在
        print(s.count("zxd"))  # 存在几个
        print(["zxd"] * 2)  # 打印出来就好了
        
        运行结果:
        True
        2
        ['zxd', 'zxd']  # 实现同样的效果
        
    2. 元字符

      • 元字符才是正则表达式的灵魂所在,介绍部分内容:

        • 字符组
        • 常用元字符(单一匹配)
        • 量词
      • 字符组

        • 字符组用[]表示,[]中出现的内容会被匹配到

          例:匹配到字符串"zxdhnbzxdznbzxdtnb"中的"hnb" "znb" "tnb"

          import re
          
          s = "zxdhnbzxdznbzxdtnb"
          print(re.findall("[hzt]nb", s))
          
          运行结果:
          ['hnb', 'znb', 'tnb']  # 将字符串中含有"hnb"、"znb"、"tnb"的部分过滤出来
          
        • []还可填入一个范围,比如[0-9a-zA-Z]它可以匹配字符串中0到9,a到z,A到Z中的字符

          例:匹配到字符串"zxd123456zxdznb"中的数字

          import re
          
          s = "zxd123456zxdznb"
          print(re.findall("[0-9]", s))
          
          运行结果:
          ['1', '2', '3', '4', '5', '6']  # 匹配到字符串中的0到9的数字
          
        • 范围遵循ascii码的从小到大规定,比如[A-z]可以匹配之间的所有字符,但[a-Z]只能匹配到a

          import re
          
          s = "asdzxcqwe123!@#"
          print(re.findall("[A-z]", s))
          print(re.findall("[a-Z]", s))
          
          运行结果:
          ['a', 's', 'd', 'z', 'x', 'c', 'q', 'w', 'e']  # [A-z]匹配成功
          sre_constants.error: bad character range a-Z at position 1  # [a-Z]报错
          
        • 字符组还可以反向过滤,在[]中加入^,比如[^123]它可以匹配字符串中除了123以外的所有字符

          例:匹配到字符串"zxdznb123456789"中除数字以外的字符

          import re
          
          s = "zxdznb123456789"
          print(re.findall("[^0-9]", s))
          
          运行结果:
          ['z', 'x', 'd', 'z', 'n', 'b']  # 匹配到字符串中除数字以外的字符
          
        • 应用举例:通过匹配判断手机号输入是否正确(有点low的例子)

          import re
          
          number = input("手机号:")
          if len(number) != 11:
              print("手机号输入有误!")
          else:
          	num = re.findall("[1][3-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]", number)
              if not num:
                  print("手机号格式不正确!")
              else:
                  print("手机号可以使用!")
          
      • 常用元字符(单一匹配)

        w 匹配字母(含中文)、数字、下划线
        W 匹配非字母(含中文)、数字、下划线
        s 匹配空白符
        S 匹配非空白符
        d 匹配数字
        D 匹配非数字
         匹配单词的边界
        B 匹配非单词的边界
        A 匹配字符串的开始
        ^ 匹配字符串的开始
         匹配字符串的结尾
        $ 匹配字符串的结尾
        匹配一个换行符
        匹配一个制表符
        . 匹配除换行符以外任意字符
        a|b 匹配字符a或b
        () 分组,匹配括号内的表达式
        [] 匹配字符组内的字符
        [^] 匹配除字符组以外的字符
        • w :匹配字符串中字母(含中文)、数字、下划线

          例:匹配到字符串"zxd123 456!@#¥"中的字母和数字

          import re
          
          s = "zxd123
          456!@#¥"
          print(re.findall("w", s))
          
          运行结果:
          ['z', 'x', 'd', '1', '2', '3', '4', '5', '6']
          
        • W :匹配字符串中非字母(含中文)、数字、下划线

          例:匹配到字符串"zxd123 456!@#¥"中的非字母和数字的内容

          import re
          
          s = "zxd123
          456!@#¥"
          print(re.findall("W", s))
          
          运行结果:
          ['
          ', '!', '@', '#', '¥']
          
        • s :匹配空白符(包含空格、制表符和换行符 )

          例:匹配到字符串"zxd 123 456 !@#¥"中的空白符

          import re
          
          s = "zxd  	123  
          456  !@#¥"
          print(re.findall("s", s))
          
          运行结果:
          [' ', ' ', '	', ' ', ' ', '
          ', ' ', ' ']
          
        • S :匹配非空白符

          例:匹配到字符串"zxd 123 456 !@#¥"中非空白符的内容

          import re
          
          s = "zxd  	123  
          456  !@#¥"
          print(re.findall("S", s))
          
          运行结果:
          ['z', 'x', 'd', '1', '2', '3', '4', '5', '6', '!', '@', '#', '¥']
          
        • d :匹配数字

          例:匹配到字符串"zxd123456zxdznb"中的数字

          import re
          
          s = "zxd123456zxdznb"
          print(re.findall("d", s))
          
          运行结果:
          ['1', '2', '3', '4', '5', '6']
          
        • D :匹配非数字

          例:匹配到字符串"zxd123456zxdznb"中的非数字的内容

          import re
          
          s = "zxd123456zxdznb"
          print(re.findall("D", s))
          
          运行结果:
          ['z', 'x', 'd', 'z', 'x', 'd', 'z', 'n', 'b']
          
        •  :匹配单词边界

          例:匹配到字符串"周杰伦-麻花藤-潘长江-赵本山-林俊周-韩周鸿-周猩猩-周星"中所有姓周的人名

          import re
          
          s = "周杰伦-麻花藤-潘长江-赵本山-林俊周-韩周鸿-周猩猩-周星"
          print(re.findall(r"周w+", s))
          
          运行结果:
          ['周杰伦', '周猩猩', '周星']
          
        • B :匹配非单词边界

          例:匹配到字符串"周杰伦-麻花藤-潘长江-赵本山-林俊周-韩周鸿-周猩猩-周星"中所有名带有周的人

          import re
          
          s = "周杰伦-麻花藤-潘长江-赵本山-林俊周-韩周鸿-周猩猩-周星"
          print(re.findall(r"w+B周w*", s))
          
          运行结果:
          ['林俊周', '韩周鸿']
          
        • A :匹配字符串的开头(不常用,知道就行)

          例:匹配到字符串"zxdhnbzxdznb"的开头

          import re
          
          s = "zxdhnbzxdznb"
          print(re.findall("Aw", s))
          
          运行结果:
          ['z']
          
        • ^ :匹配字符串的开头(常用)

          例:匹配到字符串"zxdhnbzxdznb"的开头

          import re
          
          s = "zxdhnbzxdznb"
          print(re.findall("^w", s))
          
          运行结果:
          ['z']
          
        •  :匹配字符串的结尾(不常用,知道就行)

          例:匹配到字符串"zxdhnbzxdznb"的结尾

          import re
          
          s = "zxdhnbzxdznb"
          print(re.findall("w", s))
          
          运行结果:
          ['b']
          
        • $ :匹配字符串的结尾(常用)

          例:匹配到字符串"zxdhnbzxdznb"的结尾

          import re
          
          s = "zxdhnbzxdznb"
          print(re.findall("w$", s))
          
          运行结果:
          ['b']
          
        • ^$ 结合使用时,两者之间的长度一定要和待匹配的字符串长度相同,否则匹配不上

          import re
          
          s = "zxdznb666"
          print(re.findall("^zxdznb666$", s))
          print(re.findall("^zxdznb$", s))
             
          运行结果:
          ['zxdznb666']
          []
          
        • ^$ 的应用举例:通过匹配判断手机号输入是否正确(升级版,还是很low)

          import re
          
          number = input("手机号:")
          num = re.findall("^[1][3-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$", number)  # 匹配到以1开头,以0到9结尾的一串11位数字
          if not num:
              print("手机号格式不正确!")
          else:
          	print("手机号可以使用!")
          
        • :匹配换行符

          例:匹配到字符串"zxd 123 456 !@#$"中的换行符

          import re
          
          s = "zxd  	123  
          456  !@#$"
          print(re.findall("
          ", s))
          
          运行结果:
          ['
          ']
          
        • :匹配制表符

          例:匹配到字符串"zxd 123 456 !@#$"中的制表符

          import re
          
          s = "zxd  	123  
          456  !@#$"
          print(re.findall("	", s))
             
          运行结果:
          ['	']
          
        • . :匹配除换行符任意的字符,当指定re.DOTALL时,可以匹配含换行符以内的任意字符

          例:匹配字符串"zxd123 456"中所有内容(含换行符|不含换行符)

          import re
          
          s = "zxd123
          456"
          print(re.findall(".", s))
          print(re.findall(".", s, re.DOTALL))
             
          运行结果:
          ['z', 'x', 'd', '1', '2', '3', '4', '5', '6']
          ['z', 'x', 'd', '1', '2', '3', '
          ', '4', '5', '6']
          
        • a|b :匹配字符a或b,优先匹配前面,只要前面匹配到了后面就不看了,继续向下匹配

          例:匹配到字符串"zxdnb666zxd"中的zxd666

          import re
          
          s = "zxdnb666zxd"
          print(re.findall("zxd|666", s))
          
          运行结果:
          ['zxd', '666', 'zxd']
          
        • () :分组,匹配括号内的表达式,可以在括号两端增加限制

          例:匹配到字符串"zxdnb66zxd66zxd"中的zxd,只匹配到66中间的zxd

          import re
          
          s = "zxdnb66zxd66zxd"
          print(re.findall("(zxd)", s))
          print(re.findall("66(zxd)66", s))
          
          运行结果:
          ['zxd', 'zxd', 'zxd']
          ['zxd']
          
        • [] :匹配字符组范围内的字符

        • [^] :匹配非字符组范围内的字符

      • 量词(多个匹配)

        ***** 重复零次或更多次
        + 重复一次或更多次
        重复零次或一次
        {n} 重复n次
        {n,} 重复n次或更多次
        {n,m} 重复n到m次
        • ***** :重复零次或更多次
        import re
        
        s = "zxdnb66zxd66zxd"
        print(re.findall("6*", s))
        
        运行结果:
         ['', '', '', '', '', '66', '', '', '', '66', '', '', '', '']
        
        • + :重复一次或更多次
        import re
        
        s = "zxdnb66zxd66zxd"
        print(re.findall("6+", s)) 
        
        运行结果:
        ['66', '66']
        
        • :重复零次或一次
        import re
        
        s = "zxdnb66zxd66zxd"
        print(re.findall("6?", s))
        
        运行结果:
        ['', '', '', '', '', '6', '6', '', '', '', '6', '6', '', '', '', '']
        
        • {n} :重复n次
        import re
        
        s = "zxdnb66zxd66zxd"
        print(re.findall("w{3}", s))
        
        运行结果:
        ['zxd', 'nb6', '6zx', 'd66', 'zxd']
        
        • {n,} :重复n次或更多次
        import re
        
        s = "zxdnb66-zxd-6-6zxd"
        print(re.findall("w{3,}", s))
        
        运行结果:
        ['zxdnb66', 'zxd', '6zxd']
        
        • {n,m} :重复n到m次
        import re
        
        s = "zxdnb66-zxd-6-6zxd"
        print(re.findall("w{3,5}", s))
        
        运行结果:
        ['zxdnb', 'zxd', '6zxd']
        
        • {} 的应用举例:通过匹配判断手机号输入是否正确(再次升级版)
        import re
        
        number = input("手机号:")
        num = re.findall("^[1][3-9][0-9]{9}$", number)  # 匹配到以1开头,以0到9结尾的一串11位数字
        if not num:
            print("手机号格式不正确!")
        else:
        	print("手机号可以使用!")
        
    3. 贪婪匹配和非贪婪匹配(惰性匹配)

      • 贪婪匹配:尽可能多的匹配,量词中的 * + {} 都是贪婪匹配

        import re
        
        s = "zxdznb666"
        print(re.findall("w*", s))
        print(re.findall("w+", s))
        print(re.findall("w{1,3}", s))
        
        运行结果:
        ['zxdznb666', '']
        ['zxdznb666']
        ['zxd', 'znb', '666']
        
        • 贪婪匹配底层运用到的算法:回溯算法

      • 非贪婪匹配(惰性匹配):尽可能少的匹配,量词中的 ? 是非贪婪匹配

        import re
        
        s = "zxdznb666"
        print(re.findall("w{1,3}?", s))
        
        运行结果:
        ['z', 'x', 'd', 'z', 'n', 'b', '6', '6', '6']
        
        • 非贪婪匹配底层用到的算法:先去找结束的值,再去判断规则

    4. 转义:定义规则时,会遇到类似于 这样的具有特殊意义的词,可以使用转义表示,转义有两种方式:

      • 方式一:\n
      • 方式二:r" "

    (三)正则模块re

    • 核心方法:

      re.findall() 按规则查找,返回list
      re,finditer() 按规则查找,返回一个迭代器,通过group方法取值
      re.search() 任意位置匹配,匹配到就返回结果,没匹配上返回None
      re.match() 只能从字符串开头开始匹配,匹配到就返回结果,匹配不到返回None
      • re.findall()

        • 函数定义:findall(pattern, string, flags=0)
        • 函数说明:按规则查找,返回一个列表
        import re
        
        s = "zxd123
        456!@#¥"
        print(re.findall("w", s))
        
        运行结果:
        ['z', 'x', 'd', '1', '2', '3', '4', '5', '6']
        
      • re,finditer()

        • 函数定义:finditer(pattern, string, flags=0)
        • 函数说明:按规则查找,返回一个迭代器,通过group方法取值
        import re
        
        s = "zxd"
        it = re.finditer("w", s)
        for el in it:
            print(el.group())
            
        运行结果:
        z
        x
        d
        
      • re.search()

        • 函数定义:search(pattern, string, flags=0)
        • 函数说明:任意位置匹配,匹配到就返回结果,没匹配上返回None
        import re
        
        s = "zxdnb66-zxd-6-6zxd"
        print(re.search(r"w+", s).group())
        
        运行结果:
        zxdnb66
        
        • 还可以给分组起名称,利用名称输出
          • 格式为:?P<名称>
        import re
        
        s = "<h1>hello</h1>"
        ret = re.search("<(?P<h>w+)>(?P<h1>w+)</(?P<h2>w+)>",s)
        print(ret.group("h"))
        print(ret.group("h1"))
        print(ret.group("h2"))
        
        运行结果:
        h1
        hello
        h1
        
      • re.match()

        • 函数定义:match(pattern, string, flags=0)
        • 函数说明:只能从字符串开头开始匹配,匹配到就返回结果,匹配不到返回None
        import re
        
        s = "zxdnb66-zxd-6-6zxd"
        print(re.match(r"w+", s).group())
        
        s = "-zxdnb66-zxd-6-6zxd"
        print(re.match(r"w+", s))
        
        运行结果:
        zxdnb66
        None
        
    • 其他方法

      re.split() 可按照任意分隔符进行分隔
      re.sub() 替换
      re.compile() 编译规则
      • re.split()

        • 函数定义:split(pattern, string, maxsplit=0, flags=0)
        • 函数说明:按照填入的参数进行切割,返回一个列表,将填入的参数用括号括起来,则在返回的列表中保留切割参数,还可指定最大切割次数,剩余部分作为最后一个元素存放在列表中
        import re
        
        s = "zxd-nb-666-777-888"
        print(re.split("-", s))
        print(re.split("(-)", s))
        print(re.split("-", s, maxsplit=2))
        
        运行结果:
        ['zxd', 'nb', '666', '777', '888']
        ['zxd', '-', 'nb', '-', '666', '-', '777', '-', '888']
        ['zxd', 'nb', '666-777-888']
        
      • re.sub()

        • 函数定义:sub(pattern, repl, string, count=0, flags=0)
        • 函数说明:替换,可以通过count控制替换次数
        import re
        
        s = "zxd-nb-666-777-888"
        print(re.sub("-", "|", s))
        print(re.sub("-", "|", s, 2))
        
        运行结果:
        zxd|nb|666|777|888
        zxd|nb|666-777-888
        
      • re.compile()

        • 函数定义:compile(pattern, flags=0)
        • 函数说明:编译一个正则表达式,返回一个规则对象
        import re
        
        s = "zxd-nb-666-777-888"
        obj = re.compile("w+")
        print(obj.findall(s))
        
        运行结果:
        ['zxd', 'nb', '666', '777', '888']
        

    二、logging模块

    (一)什么是日志

    • 我们在编写代码的时候,会报很多的错误,错误信息是不会自动生成的,这些错误信息是编写python解释器的程序员们预先写好的日志加入到程序中,如过触发了某种条件会显示到中控台上,我们在写程序的过程中也会不断调试,我们调试的方法一般都是使用print打印出来,这就可以通过日志显示和记录
    • 在python中使用logging模块就可以自定义日志,在我们编写程序的时候,就可以利用自定义日志来进行显示和记录
    • 最重要的一点,日志是给程序员看的,需要给用户看的还是需要print出来

    (二)logging模块

    1. logging模块的使用:

      • 基础配置型:简单、可定制化差
      • 对象配置型:复杂、可定制化强
    2. 日志分级

      日志分级 对应解释 级别数值
      debug 调试 10
      info 信息 20
      warning 警告 30
      error 错误 40
      critical 危险 50
    3. 函数式简单配置

      • 基础版日志
      import logging
      
      logging.debug('debug message')        # 调试
      logging.info('info message')          # 信息
      logging.warning('warning message')    # 警告
      logging.error('error message')        # 错误
      logging.critical('critical message')  # 危险
      
      运行结果:
      WARNING:root:warning message
      ERROR:root:error message
      CRITICAL:root:critical message
      
      • 说明:

        1. 运行时显示的的结果只有warningerrorcritical三个级别的日志信息,logging模块默认从warning级别(30)的日志开始输出
        2. 输出的日志由日志级别、用户名、日志信息三部分构成
      • 通过日志配置函数 logging.basicConfig() 可以调整输出级别、日志内容等信息,配置函数如下:

        • 函数定义:basicConfig(**kwargs)
        • 关键字参数说明:
        filename 指定文件,日志内容将会存储在文件中
        filemode 文件打开方式,指定了filename后才能指定,默认为"a"
        format 日志显示格式,参数如下
        datefmt 时间显示格式
        level 日志级别
        • 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
        
        logging.basicConfig(level=logging.DEBUG,  # 调整日志输出等级
                            format="Time:'%(asctime)s' FilePath:'%(pathname)s' [line:%(lineno)d] %(levelname)s Message:'%(message)s'",
                            datefmt='%Y-%m-%d %H:%M:%S')
        logging.debug('debug message')
        logging.info('info message')
        logging.warning('warning message')
        logging.error('error message')
        logging.critical('critical message')
        
        运行结果:
        Time:'2019-10-03 15:09:06' FilePath:'D:/python_S26/day17/exercise.py' [line:226] DEBUG Message:'debug message'
        Time:'2019-10-03 15:09:06' FilePath:'D:/python_S26/day17/exercise.py' [line:227] INFO Message:'info message'
        Time:'2019-10-03 15:09:06' FilePath:'D:/python_S26/day17/exercise.py' [line:228] WARNING Message:'warning message'
        Time:'2019-10-03 15:09:06' FilePath:'D:/python_S26/day17/exercise.py' [line:229] ERROR Message:'error message'
        Time:'2019-10-03 15:09:06' FilePath:'D:/python_S26/day17/exercise.py' [line:230] CRITICAL Message:'critical message'
        
    4. 列举三个应用,理解日志的用法

      • logging.debug()的应用
      import logging
      
      logging.basicConfig(level=logging.DEBUG,  # 这里可以通过修改输出等级来控制需要调试的时候输出
                          format="Time:'%(asctime)s' FilePath:'%(pathname)s' [line:%(lineno)d] %(levelname)s Message:'%(message)s'",
                          datefmt='%Y-%m-%d %H:%M:%S')
      lst = list()
      for el in range(5):
          lst.append(el)
          logging.debug(lst)
      print(lst)
      
      运行结果:
      [0, 1, 2, 3, 4]  # 并发问题导致先输出lst
      Time:'2019-10-03 17:16:49' FilePath:'D:/python_S26/day17/exercise.py' [line:239] DEBUG Message:'[0]'
      Time:'2019-10-03 17:16:49' FilePath:'D:/python_S26/day17/exercise.py' [line:239] DEBUG Message:'[0, 1]'
      Time:'2019-10-03 17:16:49' FilePath:'D:/python_S26/day17/exercise.py' [line:239] DEBUG Message:'[0, 1, 2]'
      Time:'2019-10-03 17:16:49' FilePath:'D:/python_S26/day17/exercise.py' [line:239] DEBUG Message:'[0, 1, 2, 3]'
      Time:'2019-10-03 17:16:49' FilePath:'D:/python_S26/day17/exercise.py' [line:239] DEBUG Message:'[0, 1, 2, 3, 4]'
      
      • logging.info()的应用
      import logging
      
      logging.basicConfig(level=logging.INFO,
                          format="Time:'%(asctime)s' FilePath:'%(pathname)s' [line:%(lineno)d] %(levelname)s Message:'%(message)s'",
                          datefmt='%Y-%m-%d %H:%M:%S')
      userinfo = dict()
      user = input("账号:")
      pwd = input("密码:")
      userinfo[user] = pwd
      logging.info(f"注册的账号:{user},注册的密码:{pwd}")  # 记录程序运行时的信息
      
      运行结果:
      账号:zxd
      密码:zxd123
      Time:'2019-10-03 17:35:07' FilePath:'D:/python_S26/day17/exercise.py' [line:251] INFO Message:'注册的账号:zxd,注册的密码:zxd123'
      
      • logging.error()的应用
      import logging
      
      logging.basicConfig(level=logging.INFO,
                          format="Time:'%(asctime)s' FilePath:'%(pathname)s' [line:%(lineno)d] %(levelname)s Message:'%(message)s'",
                          datefmt='%Y-%m-%d %H:%M:%S')
      try:
          def division(a, b):
              c = a / b
              return c
      
          division(3, 0)
      except ZeroDivisionError:
          print("除数不能为0")
          logging.error("输入除数为0")
          
      运行结果:
      除数不能为0
      Time:'2019-10-03 17:51:46' FilePath:'D:/python_S26/day17/exercise.py' [line:266] ERROR Message:'输入除数为0'
      
    5. 函数式简单配置有两个弊端:

      • 编码不能修改
      • 中控台和文件不能同时进行(要么在中控台显示,要么写入文件)
    6. logger对象配置

      • 利用logger对象来操作日志文件,具体流程如下:
        • 创建一个logger对象,用来操作日志
        • 创建一个文件管理操作符,用来写入文件
        • 创建一个屏幕管理操纵符, 用来屏幕显示
        • 创建一个日志输出的格式
        • 将操作符与输出格式进行绑定
        • 将logger对象与操作符进行绑定
      import logging
      
      logger = logging.getLogger()
      # 创建一个logger对象,用来操作日志
      fh = logging.FileHandler("log.log", encoding="utf-8")
      # 创建一个文件管理操作符,用来写入文件
      sh = logging.StreamHandler()
      # 创建一个屏幕管理操纵符, 用来屏幕显示
      fmt = logging.Formatter("Time:'%(asctime)s' FilePath:'%(pathname)s' [line:%(lineno)d] %(levelname)s Message:'%(message)s'")
      # 创建一个日志输出的格式
      
      fh.setFormatter(fmt)
      # 将文件管理操作符与输出格式进行绑定
      sh.setFormatter(fmt)
      # 将屏幕管理操作符与输出格式进行绑定
      logger.addHandler(fh)
      # 将logger对象与文件管理操作符进行绑定
      logger.addHandler(sh)
      # 将logger对象与屏幕管理操作符进行绑定
      
      logger.setLevel(logging.DEBUG)
      # 调整日志输出级别
      
      logger.debug('debug message')
      logger.info('info message')
      logger.warning('warning message')
      logger.error('error message')
      logger.critical('critical message')
      
      运行结果:
      Time:'2019-10-03 18:31:18,217' FilePath:'D:/python_S26/day17/exercise.py' [line:283] DEBUG Message:'debug message'
      Time:'2019-10-03 18:31:18,217' FilePath:'D:/python_S26/day17/exercise.py' [line:284] INFO Message:'info message'
      Time:'2019-10-03 18:31:18,217' FilePath:'D:/python_S26/day17/exercise.py' [line:285] WARNING Message:'warning message'
      Time:'2019-10-03 18:31:18,217' FilePath:'D:/python_S26/day17/exercise.py' [line:286] ERROR Message:'error message'
      Time:'2019-10-03 18:31:18,218' FilePath:'D:/python_S26/day17/exercise.py' [line:287] CRITICAL Message:'critical message'
      
      
      • 说明:
        • 通过logger对象来操作日志可以让中控台和文件同时进行
        • 通过logger对象写入文件时,可以指定编码方式
        • 灵活性高,创建的对象之间没有关系,通过绑定链在一起,完全可以绑定两个文件管理操作符来写入不同的文件,也可以绑定不同的输出格式
  • 相关阅读:
    URL Rewrite
    Visual Studio调试Asp程序
    IE6下雪碧图多次请求fix方法
    使用antixss防御xss
    字典及其增删改查,解构用法
    逻辑运算,编码问题
    字符串数据类型及其用法
    数据类型,if 语句,while语句
    列表和字典循环遍历时的删除问题,集合
    列表,及其增删改查,元组
  • 原文地址:https://www.cnblogs.com/tianlangdada/p/11628400.html
Copyright © 2020-2023  润新知