今日主要内容

  • 正则表达式
  • 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 匹配单词的边界
      \B 匹配非单词的边界
      \A 匹配字符串的开始
      ^ 匹配字符串的开始
      \Z 匹配字符串的结尾
      $ 匹配字符串的结尾
      \n 匹配一个换行符
      \t 匹配一个制表符
      . 匹配除换行符以外任意字符
      a|b 匹配字符a或b
      () 分组,匹配括号内的表达式
      [] 匹配字符组内的字符
      [^] 匹配除字符组以外的字符
      • \w :匹配字符串中字母(含中文)、数字、下划线

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

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

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

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

        例:匹配到字符串"zxd \t123 \n456 !@#¥"中的空白符

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

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

        import re
        
        s = "zxd  \t123  \n456  !@#¥"
        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']
      • \b :匹配单词边界

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

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

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

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

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

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

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

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

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

        import re
        
        s = "zxdhnbzxdznb"
        print(re.findall("\w\Z", 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("手机号可以使用!")
      • \n :匹配换行符

        例:匹配到字符串"zxd \t123 \n456 !@#$"中的换行符

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

        例:匹配到字符串"zxd \t123 \n456 !@#$"中的制表符

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

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

        import re
        
        s = "zxd123\n456"
        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', '\n', '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这样的具有特殊意义的词,可以使用转义表示,转义有两种方式:

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

(三)正则模块re

  • 核心方法:

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

      • 函数定义:findall(pattern, string, flags=0)
      • 函数说明:按规则查找,返回一个列表
      import re
      
      s = "zxd123\n456!@#¥"
      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对象写入文件时,可以指定编码方式
      • 灵活性高,创建的对象之间没有关系,通过绑定链在一起,完全可以绑定两个文件管理操作符来写入不同的文件,也可以绑定不同的输出格式

python基础(十七)的更多相关文章

  1. python六十七课——网络编程(基础知识了解)

    网络编程: 什么是网络编程? 网络:它是一种隐形的媒介:可以将多台计算机使用(将它们连接到一起) 网络编程:将多台计算机之间可以相互通信了(做数据交互) 一旦涉及到网络编程,划分为两个方向存在,一方我 ...

  2. 十七. Python基础(17)--正则表达式

    十七. Python基础(17)--正则表达式 1 ● 正则表达式 定义: Regular expressions are sets of symbols that you can use to cr ...

  3. python基础内容目录

    一  python基础 二  python基础数据类型 三  python文件操作及函数初识 四  python函数进阶 五  python装饰器 六  python迭代器与生成器 七  python ...

  4. 孤荷凌寒自学python第二十七天python的datetime模块及初识datetime.date模块

    孤荷凌寒自学python第二十七天python的datetime模块及初识datetime.date模块 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.datetime模块 dateti ...

  5. 孤荷凌寒自学python第十七天初识Python的函数

    孤荷凌寒自学python第十七天初识Python的函数 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 函数是能够完成指定运算并返回运算结果的代码块.是结构化编程重要的结构. 我首先发现pyt ...

  6. 初【001】——Python 基础知识

    1.python基础入门 提示: 语法基于python3.x版本(会提示2.x版本和3.x版本的区别) Python命令行将以>>>开始,比如 >>>print ( ...

  7. python基础认识

    Python基础 一.    简介 Python是著名的“龟叔”Guido van Rossum在1989年圣诞节期间,为了打发无聊的圣诞节而编写的一个编程语言.豆瓣,Google.Yahoo等,甚至 ...

  8. python之最强王者(2)——python基础语法

    背景介绍:由于本人一直做java开发,也是从txt开始写hello,world,使用javac命令编译,一直到使用myeclipse,其中的道理和辛酸都懂(请容许我擦干眼角的泪水),所以对于pytho ...

  9. Python开发【第二篇】:Python基础知识

    Python基础知识 一.初识基本数据类型 类型: int(整型) 在32位机器上,整数的位数为32位,取值范围为-2**31-2**31-1,即-2147483648-2147483647 在64位 ...

随机推荐

  1. 猫眼电影和电影天堂数据csv和mysql存储

    字符串常用方法 # 去掉左右空格 'hello world'.strip() # 'hello world' # 按指定字符切割 'hello world'.split(' ') # ['hello' ...

  2. HTML 画布(摘自菜鸟教程)

    颜色.样式和阴影 属性 描述 fillStyle 设置或返回用于填充绘画的颜色.渐变或模式. strokeStyle 设置或返回用于笔触的颜色.渐变或模式. shadowColor 设置或返回用于阴影 ...

  3. 转载 江南一点雨 一键部署docker

    一键部署 Spring Boot 到远程 Docker 容器,就是这么秀!   不知道各位小伙伴在生产环境都是怎么部署 Spring Boot 的,打成 jar 直接一键运行?打成 war 扔到 To ...

  4. 关于turtle画蟒蛇小实例

    import turtle turtle.setup(800,600) turtle.pensize(25) turtle.pencolor('blue') turtle.penup() #抬笔 tu ...

  5. Go语言标准库之fmt

    fmt标准库是我们在学习Go语言过程中接触最早最频繁的一个了,本文介绍了fmtb包的一些常用函数. fmt fmt包实现了类似C语言printf和scanf的格式化I/O.主要分为向外输出内容和获取输 ...

  6. Git使用教程 Windows使用Git全攻略

    在Windows上安装Git 我们需要先把Git的安装包下载下来,访问网址:https://git-for-windows.github.io/ 或者百度网盘:链接: https://pan.baid ...

  7. android 中Application的作用

    转自:lieren666 博客地址:http://blog.csdn.net/lieren666/article/details/7598288 What is Application Applica ...

  8. jvm内存溢出问题的定位方法

    jvm内存溢出问题的定位方法 今天给大家带来JVM体验之内存溢出问题的定位方法. 废话不多说直接开始: 一.Java堆溢出 测试代码如下: import java.util.*; public cla ...

  9. 〈三〉ElasticSearch的认识:搜索、过滤、排序

    目录 上节回顾 本节前言 文档的搜索 URL参数条件搜索 请求体条件搜索 语法与示例: 补充: 小节总结: 文档的过滤filter 语法与举例: filter与bool constant_score ...

  10. ansible-playbook流程控制-loops循环使用

    1. ansible-playbook流程控制-loops循环使用    有时你想要多次重复任务.在计算机编程中,这称为循环.common ansible循环包括使用文件模块更改多个文件和/或目录的所 ...