今日主要内容

  • 正则表达式
  • 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. JavaScript入门之AJAX:原生ajax

    背景 传统的Web应用允许用户端填写表单(form),当提交表单时就向网页服务器发送一个请求.服务器接收并处理传来的表单,然后送回一个新的网页,但这个做法浪费了许多带宽,因为在前后两个页面中的大部分H ...

  2. 2019nc#10

    题号 标题 已通过代码 题解/讨论 通过率 团队的状态 A Blackjack 点击查看 背包DP 32/109 补好了 B Coffee Chicken 点击查看 进入讨论 738/2992  通过 ...

  3. CF 462 C. A Twisty Movement 分段想 线段树 或 dp

    题意 有一个只包含1和2的序列,试翻转一个区间,使得结果中非连续非递减数列最长. 思路 一. 作出1的前缀计数和为cnt1,2的后缀计数和为cnt2, 由于要找出[1,1,1][2,2,2][1,1, ...

  4. HDU-4027-Can you answer these queries?线段树+区间根号+剪枝

    传送门Can you answer these queries? 题意:线段树,只是区间修改变成 把每个点的值开根号: 思路:对[X,Y]的值开根号,由于最大为 263.可以观察到最多开根号7次即为1 ...

  5. lightoj 1119 - Pimp My Ride(状压dp)

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1119 题解:状压dp存一下车有没有被搞过的状态就行. #include < ...

  6. 基于.net EF6 MVC5+WEB Api 的Web系统框架总结(3)-项目依赖注入

    简介 依赖注入主要是一种结构性的模式,注重的是类与类之间的结构,它要达到的目的就是设计原则中最少知道和合成复用的原则,减少内部依赖,履行单一职责,最终就是强解耦.依赖注入目前最好的实现就是依赖注入容器 ...

  7. SVN分支与主干合并

    1.主干合并到分支 1在本地trunk中先update一下,有冲突的解决冲突,保证trunk和repository已经完全同步, 2.在/branches /MyProject上右键,依次选择”Tor ...

  8. MariaDB数据库自学一

    在CentOS下安装Mariadb 数据库,命令: yum -y mariadb mariadb.server 等待几分钟后就可以自动完成安装了,然后启动对应的服务: systemctl  start ...

  9. Git使用(一)安装配置过程-Win7

    公司项目需要使用Git作为项目的代码库管理工具.正好借此机会写个安装过程 1.首先下载Git下载地址:https://git-scm.com/download/win 当前下载版本:Git-2.13. ...

  10. 谁动了我的奶酪?--java实例初始化的顺序问题

    故事背景 有一天,老鼠小白发现了一个奇怪的问题,它的奶酪的生产日期被谁搞丢了,不知道奶酪是否过期,可怎么吃呀? 让我们来看看吧 import java.util.Date;public class C ...