常用模块
内容目录
什么是模块?
常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。
但其实import加载的模块分为四个通用类别:
1 使用python编写的代码(.py文件)
2 已被编译为共享库或DLL的C或C++扩展
3 包好一组模块的包
4 使用C编写并链接到python解释器的内置模块
为什么要使用模块
随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理
这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用
模块的导入和使用,应在程序开始的地方
在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict
namedtuple和OrderedDict等。
namedtuple:
生成可以使用名字来访问元素内容的tuple
#表示坐标 from collections import namedtuple point = namedtuple('point',['x','y','z']) p = point(1,2,3) print(p.x,p.y,p.z) #1 2 3 #表示花色 car = namedtuple('card',['suit','number']) h = car('桃花','9') print(h.suit,h.number) #桃花 9
deque
使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。
deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈
deque的方法有append()、appendleft、pop、popleft、insert等
from collections import deque lis = deque(['a','b','c']) lis.append('z') print(lis) #deque(['a', 'b', 'c', 'z']) lis.pop() print(lis) #deque(['a', 'b', 'c']) lis.popleft() print(lis) #deque(['b', 'c']) lis.insert(0,'k') print(lis) #deque(['k', 'b', 'c'])
OrdereDict
使字典的插入变得有序
from collections import OrderedDict dic = dict([('a',1),('b',2),('c',3)]) print(dic) #{'a': 1, 'b': 2, 'c': 3} dic1 = OrderedDict([('a',1),('b',2),('c',3)]) print(dic1) #OrderedDict([('a', 1), ('b', 2), ('c', 3)])
Counter
用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value
from collections import Counter a = ('asddjfkskakdanzsa') print(Counter(a)) #Counter({'a': 4, 's': 3, 'd': 3, 'k': 3, 'j': 1, 'f': 1, 'n': 1, 'z': 1})
队列类似于一条管道,元素先进先出,进put(arg),取get()
有一点需要注意的是:队列都是在内存中操作,进程退出,队列清空,另外,队列也是一个阻塞的形态.
队列有很多中,但都依赖模块queue
|队列方式|特点|
|---|---|
|queue.Queue|先进先出队列|
|queue.LifoQueue|后进先出队列|
|queue.PriorityQueue|优先级队列|
|queue.deque|双线队列|
堆栈 : 先进后出
队列 :先进先出 FIFO
put 放数据 get,取数据(默认阻塞),Queue.get([block[, timeout]])获取队列,timeout等待时间 empty,如果队列为空,返回True,反之False qsize,显示队列中真实存在的元素长度 maxsize,最大支持的队列长度,使用时无括号 join,实际上意味着等到队列为空,再执行别的操作 take_done,在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号 full,如果队列满了,返回True,反之False
import queue q=queue.Queue(5) #如果不设置长度,默认为无限长 print(q.maxsize) #注意没有括号 q.put(123) q.put(456) q.put(789) q.put(100) q.put(111) q.put(233) print(q.get()) #如此打印时候是阻塞的,为什么呢,因为创建了5个元素长度的队列,但我put进去了6个,所以就阻塞了.如果少写一个能显示出正确的123
import queue q = queue.LifoQueue() q.put(12) q.put(34) print(q.get()) #34
import queue q = queue.PriorityQueue() q.put((3,'aaaaa')) q.put((3,'bbbbb')) q.put((1,'ccccc')) q.put((3,'ddddd')) print(q.get()) #(1, 'ccccc') print(q.get()) #(3, 'aaaaa')
import queue q = queue.deque() q.append(123) q.append(456) q.appendleft(789) print(q.pop()) #456 print(q.popleft()) #789
解决程序解耦,较少的资源解决高并发的问题
表示时间的三种方法
时间戳(timestamp) --> 通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型
import time print(type(time.time())) #<class 'float'> print(time.time()) #1567942962.9401913
格式化的时间字符串(Format String) 例:‘1999-12-06’
%y 两位数的年份表示(00-99) %Y 四位数的年份表示(000-9999) %m 月份(01-12) %d 月内中的一天(0-31) %H 24小时制小时数(0-23) %I 12小时制小时数(01-12) %M 分钟数(00=59) %S 秒(00-59) %a 本地简化星期名称 %A 本地完整星期名称 %b 本地简化的月份名称 %B 本地完整的月份名称 %c 本地相应的日期表示和时间表示 %j 年内的一天(001-366) %p 本地A.M.或P.M.的等价符 %U 一年中的星期数(00-53)星期天为星期的开始 %w 星期(0-6),星期天为星期的开始 %W 一年中的星期数(00-53)星期一为星期的开始 %x 本地相应的日期表示 %X 本地相应的时间表示 %Z 当前时区的名称 %% %号本身
import time print(time.strftime('%Y-%m-%d %H:%M:%S')) #2019-09-08 19:48:01
元组(struct_time) --> 元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天等)
#时间元组:localtime将一个时间戳转换为当前时区的struct_time import time print(time.localtime()) #time.struct_time(tm_year=2019, tm_mon=9, tm_mday=8, tm_hour=19, tm_min=55, tm_sec=36, tm_wday=6, tm_yday=251, tm_isdst=0)

时间戳(timestamp)-->元组(struct_time)
#time.gmtime(时间戳) #UTC时间,与英国伦敦当地时间一致 #time.localtime(时间戳) #当地时间。例如我们现在在北京执行这个方法:与UTC时间相差8小时,UTC时间+8小时 = 北京时间 import time print(time.localtime()) #time.struct_time(tm_year=2019, tm_mon=9, tm_mday=8, tm_hour=20, tm_min=3, tm_sec=26, tm_wday=6, tm_yday=251, tm_isdst=0) print(time.gmtime()) #time.struct_time(tm_year=2019, tm_mon=9, tm_mday=8, tm_hour=12, tm_min=3, tm_sec=59, tm_wday=6, tm_yday=251, tm_isdst=0) print(time.gmtime(1500000000)) # time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=2, tm_min=40, tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0)
元组(struct_time)--> 格式化时间(Format String)
# time.stftime import time time.localtime() print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(15000000)))
格式化时间(Format String)-->元组(struct_time)
time.strptime() import time print(time.strptime('2018-08-08','%Y-%m-%d')) time.struct_time(tm_year=2018, tm_mon=8, tm_mday=8, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=2, tm_yday=220, tm_isdst=-1)
元组(struct_time)-->时间戳(timestamp)
import time print(time.mktime(time.localtime())) #1567946329.0 print(time.time()) #1567946329.456197

元组(struct_time) --> %a %b %d %H:%M:%S %Y串
#time.asctime(结构化时间) 如果不传参数,直接返回当前时间的格式化串 import time print(time.asctime(time.localtime(1500000000))) #Fri Jul 14 10:40:00 2017 print(time.asctime()) #Sun Sep 8 20:41:43 2019
时间戳 --> %a %b %d %H:%M:%S %Y串
import time #time.ctime(时间戳) 如果不传参数,直接返回当前时间的格式化串 print(time.ctime(1500000000)) #Fri Jul 14 10:40:00 2017 print(time.ctime()) #Sun Sep 8 20:42:56 2019
datetime.now() # 获取当前datetime
datetime.utcnow() # 获取当前格林威治时间
from datetime import datetime #获取当前本地时间 a=datetime.now() print('当前日期:',a) #当前日期: 2019-09-08 21:03:12.067265 #获取当前世界时间 b=datetime.utcnow() print('世界时间:',b) #世界时间: 2019-09-08 13:03:12.067265
datetime(2017, 5, 23, 12, 20) # 用指定日期时间创建datetime
from datetime import datetime #用指定日期创建 c=datetime(2017, 5, 23, 12, 20) print('指定日期:',c)
datetime转化字符串类型
''' Saturday, September 30, 2017 9/30/2017 9:22:17 AM September 30, 2017''' from datetime import datetime j=datetime(2017,9,30,10,3,43) print(j.strftime('%A,%B %d,%Y')) #Saturday,September 30,2017 k=datetime(2017,9,30,9,22,17) print(k.strftime('%m/%d/%Y %I:%M:%S%p')) #09/30/2017 09:22:17AM l=datetime(2017,9,30) print(l.strftime('%B %d,%Y')) #September 30,2017
今天是这周的第?天
今天是今年的第?天
今周是今年的第?周
今天是当月的第?天
from datetime import datetime import locale locale.setlocale(locale.LC_CTYPE, 'chinese') #获取当前系统时间 m=datetime.now() print(m.strftime('今天是这周的第%w天')) #今天是这周的第0天 print(m.strftime('今天是今年的第%j天')) #今天是今年的第251天 print(m.strftime('今周是今年的第%W周')) #今周是今年的第35周 print(m.strftime('今天是当月的第%d天')) #今天是当月的第08天
字符串转化datetime类型
'2017/9/30' '2017年9月30日星期六' '2017年9月30日星期六8时42分24秒' '9/30/2017' '9/30/2017 8:42:50 ' from datetime import datetime d=datetime.strptime('2017/9/30','%Y/%m/%d') print(d) #2017-09-30 00:00:00 e=datetime.strptime('2017年9月30日星期六','%Y年%m月%d日星期六') print(e) #2017-09-30 00:00:00 f=datetime.strptime('2017年9月30日星期六8时42分24秒','%Y年%m月%d日星期六%H时%M分%S秒') print(f) #2017-09-30 08:42:24 g=datetime.strptime('9/30/2017','%m/%d/%Y') print(g) #2017-09-30 00:00:00 h=datetime.strptime('9/30/2017 8:42:50 ','%m/%d/%Y %H:%M:%S ') print(h) #2017-09-30 08:42:50
跨年跨越计算天数
import datetime def days(str1,str2): date1 = datetime.datetime.strptime(str1[0:10], "%Y-%m-%d") date2 = datetime.datetime.strptime(str2[0:10], "%Y-%m-%d") num = (date1 - date2).days return num def months(str1,str2): year1 = datetime.datetime.strptime(str1[0:10], "%Y-%m-%d").year year2 = datetime.datetime.strptime(str2[0:10], "%Y-%m-%d").year month1 = datetime.datetime.strptime(str1[0:10], "%Y-%m-%d").month month2 = datetime.datetime.strptime(str2[0:10], "%Y-%m-%d").month num = (year1 - year2) * 12 + (month1 - month2) return num jiuyue = '2019-09-25' shiyue = '2019-10-01' print(days(shiyue,jiuyue)) #6 yijiu = '2019-12-30' erling = '2020-01-01' print(days(erling,yijiu)) #2
#题目: 已知公元1年1月1日是星期一,请编写一个程序,只要输入年月日,就能自动回答当天是星期几。 # 蔡勒公式 # w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1 # 以上公式只适合于1582年10月15日之后的情形 weeknum = ['星期一','星期二','星期三','星期四','星期五','星期六','星期日'] ymr = input('请输入年月日(格式:年-月-日):') y,m,r = ymr.split('-') yc,yy= y[0:2],y[2:] day = int(yy) + int(yy)//4 + int(yc)//4 -2*int(yc) + 26*(int(m)+1)//10 + int(r) -1 xq = day%7 print('今天是星期%s'%weeknum[(xq-1)]) #完整 monthnumr = [0,31,59,90,120,151,181,212,243,273,304,334] monthnump = [0,31,60,91,121,152,182,213,244,274,305,335] weeknum = ['星期一','星期二','星期三','星期四','星期五','星期六','星期日'] ymd = input('请输入年月日,(格式:年-月-日):') y,m,d = ymd.split('-') md = 0 if int(y) % 4 ==0 and int(y) % 100 != 0: #闰年 a = monthnumr[(int(m)-1)] md += a else: a = monthnump[(int(m) - 1)] md += a daynum = (int(y)-1)//4 + (int(y)-1)*365 + md + int(d) print('今天是星期%s'%weeknum[(daynum%7 - 3)])
claendar模块
打印某一年和某一个月的月历
import calendar print(calendar.prcal(2019)) ''' 2019 January February March Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 1 2 3 1 2 3 7 8 9 10 11 12 13 4 5 6 7 8 9 10 4 5 6 7 8 9 10 14 15 16 17 18 19 20 11 12 13 14 15 16 17 11 12 13 14 15 16 17 21 22 23 24 25 26 27 18 19 20 21 22 23 24 18 19 20 21 22 23 24 28 29 30 31 25 26 27 28 25 26 27 28 29 30 31 April May June Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 7 1 2 3 4 5 1 2 8 9 10 11 12 13 14 6 7 8 9 10 11 12 3 4 5 6 7 8 9 15 16 17 18 19 20 21 13 14 15 16 17 18 19 10 11 12 13 14 15 16 22 23 24 25 26 27 28 20 21 22 23 24 25 26 17 18 19 20 21 22 23 29 30 27 28 29 30 31 24 25 26 27 28 29 30 July August September Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 7 1 2 3 4 1 8 9 10 11 12 13 14 5 6 7 8 9 10 11 2 3 4 5 6 7 8 15 16 17 18 19 20 21 12 13 14 15 16 17 18 9 10 11 12 13 14 15 22 23 24 25 26 27 28 19 20 21 22 23 24 25 16 17 18 19 20 21 22 29 30 31 26 27 28 29 30 31 23 24 25 26 27 28 29 30 October November December Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 1 2 3 1 7 8 9 10 11 12 13 4 5 6 7 8 9 10 2 3 4 5 6 7 8 14 15 16 17 18 19 20 11 12 13 14 15 16 17 9 10 11 12 13 14 15 21 22 23 24 25 26 27 18 19 20 21 22 23 24 16 17 18 19 20 21 22 28 29 30 31 25 26 27 28 29 30 23 24 25 26 27 28 29 30 31 ''' cal = calendar.month(2019,9) print(cal) ''' September 2019 Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30''' print(calendar.leapdays(2000,2018)) #返回2000~2018内的闰年数 #5 print(calendar.weekday(2018,11,2)) ##返回2018.11.2是星期几,0-6 #4
import random #随机小数 print(random.random()) # 大于0且小于1之间的小数 #0.35821491003002726 print(random.uniform(1,3)) #大于1小于3的小数 #2.6165072321247864 # #随机整数 print(random.randint(1,5)) # 大于等于1且小于等于5之间的整数 #3 print(random.randrange(1,10,2)) # 大于等于1且小于10之间的奇数 #9 # #随机选择一个返回 print(random.choice([1,'23',[4,5]])) # #1或者23或者[4,5] # #随机选择多个返回,返回的个数为函数的第二个参数 print(random.sample([1,'23',[4,5]],2)) # #列表元素任意2个组合 # [[4, 5], '23'] # #打乱列表顺序 item=[1,3,5,7,9] random.shuffle(item) # 打乱次序 print(item) # [5, 1, 3, 7, 9]
os模块
os模块是与操作系统交互的一个接口
os.makedirs('dirname1/dirname2') 可生成多层递归目录 os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推(同一目录下) os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 os.remove() 删除一个文件 os.rename("oldname","newname") 重命名文件/目录 os.stat('path/filename') 获取文件/目录信息 os.system("bash command") 运行shell命令,直接显示 os.popen("bash command).read() 运行shell命令,获取执行结果 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd os.path os.path.abspath(path) 返回path规范化的绝对路径 os.path.split(path) 将path分割成目录和文件名二元组返回 os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素 os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素 os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False os.path.isabs(path) 如果path是绝对路径,返回True os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 os.path.getatime(path) 返回path所指向的文件或者目录的最后访问时间 os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间 os.path.getsize(path) 返回path的大小
注意:os.stat('path/filename') 获取文件/目录信息 的结构说明
stat 结构: st_mode: inode 保护模式 st_ino: inode 节点号。 st_dev: inode 驻留的设备。 st_nlink: inode 的链接数。 st_uid: 所有者的用户ID。 st_gid: 所有者的组ID。 st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。 st_atime: 上次访问的时间。 st_mtime: 最后一次修改的时间。 st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是创建时间(详细信息参见平台的文档)。
os.sep 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/" os.linesep 输出当前平台使用的行终止符,win下为"\r\n",Linux下为"\n" os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为: os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
sys.argv[] 命令行参数List,第一个元素是程序本身路径 (为一个列表,里边的项为用户输入的参数,参数是从程序外部输入的,而非代码本身的什么地方 要想看到它的效果就应该 将程序保存了,从外部来运行程序并给出参数) sys.exit(n) 退出程序,正常退出时exit(0),错误退出sys.exit(1) sys.version 获取Python解释程序的版本信息 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 sys.platform 返回操作系统平台名称
import sys try: sys.exit(1) except SystemExit as e: print(e)
序列化模块
序列化 —— 转向一个字符串数据类型
序列 —— 字符串
数据存储
网络上传输的时候
从数据类型 --> 字符串的过程 序列化
从字符串 --> 数据类型的过程 反序列化
json # 数字 字符串 列表 字典 元组
通用的序列化格式
只有很少的一部分数据类型能够通过json转化成字符串
pickle
所有的python中的数据类型都可以转化成字符串形式
pickle序列化的内容只有python能理解
且部分反序列化依赖python代码
shelve
序列化句柄
使用句柄直接操作,非常方便
json dumps(dump对文件的处理)序列化方法 loads(load对文件的处理)反序列化方法
dic = {1:"a",2:'b'}
print(type(dic),dic) #<class 'dict'> {1: 'a', 2: 'b'}
import json
str_d = json.dumps(dic) # 序列化
print(type(str_d),str_d) #<class 'str'> {"1": "a", "2": "b"}
dic_d = json.loads(str_d) # 反序列化
print(type(dic_d),dic_d) #<class 'dict'> {'1': 'a', '2': 'b'}
import json # json dump load dic = {1:"a",2:'b'} f = open('fff','w',encoding='utf-8') json.dump(dic,f) f.close() f = open('fff') res = json.load(f) f.close() print(type(res),res) #<class 'dict'> {'1': 'a', '2': 'b'} #中文序列化 import json # json dump load dic = {1:"中国",2:'b'} f = open('fff','w',encoding='utf-8') json.dump(dic,f,ensure_ascii=False) f.close() f = open('fff',encoding='utf-8') res1 = json.load(f) f.close() print(type(res1),res1) #<class 'dict'> {'1': '中国', '2': 'b'} l = [{'k':'111'},{'k2':'111'},{'k3':'111'}] f = open('file','w') import json for dic in l: str_dic = json.dumps(dic) f.write(str_dic+'\n') f.close() f = open('file') import json l = [] for line in f: dic = json.loads(line.strip()) l.append(dic) f.close() print(l)
pickle dumps(dump对文件的处理)序列化方法 loads(load对文件的处理)反序列化方法
import pickle dic = {'k1':'v1','k2':'v2','k3':'v3'} str_dic = pickle.dumps(dic) print(str_dic) #一串二进制内容 #b'\x80\x03}q\.... dic2 = pickle.loads(str_dic) print(dic2) #{'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
import pickle import time struct_time1 = time.localtime(1000000000) struct_time2 = time.localtime(2000000000) f = open('pickle_file','wb') pickle.dump(struct_time1,f) pickle.dump(struct_time2,f) f.close() import pickle f = open('pickle_file','rb') struct_time1 = pickle.load(f) struct_time2 = pickle.load(f) print(struct_time1.tm_year) print(struct_time2.tm_year) f.close()
shelve直接对文件句柄操作,就可以存入数据
import shelve f = shelve.open('shelve_file') f['key'] = {'int':10, 'float':9.5, 'string':'Sample data'} #直接对文件句柄操作,就可以存入数据 f.close() import shelve f1 = shelve.open('shelve_file') existing = f1['key'] #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错 f1.close() print(existing) import shelve f = shelve.open('shelve_file', flag='r') existing = f['key'] print(existing) f.close() import shelve f1 = shelve.open('shelve_file') print(f1['key']) f1['key']['new_value'] = 'this was not here before' f1.close() f2 = shelve.open('shelve_file', writeback=True) print(f2['key']) f2.close()
正则表达式
正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑
import re phone_number = input('please input your phone number : ') if re.match('^(13|14|15|18)[0-9]{9}$',phone_number): print('是合法的手机号码') else: print('不是合法的手机号码')
正则表达式基础
一、作用:1、检验某一段字符串是否符号规则
2、从某一段文字中找到符合规则的字符串
二、字符
|
正则表达式 |
待匹配字符 |
匹配结果 |
说明 |
|
. |
8as |
8as |
匹配除换行符以外的任意字符 |
|
\w |
A1_ |
A1_ |
匹配字母数字或下划线 |
|
\s |
|
|
匹配空白字符 |
|
\d |
123 |
123 |
匹配数字 |
|
\n |
|
|
匹配换行符 |
|
\t |
|
|
匹配制表符 |
|
^(^qw) |
qws |
qw |
匹配字符串的开始 |
|
$(we$) |
qwe |
we |
匹配字符串的结束 |
|
\W |
11s |
11 |
匹配非字母数字或下划线 |
|
\S |
11d |
11d |
匹非配空白字符 |
|
\D |
Sd1 |
Sd |
匹配非数字 |
|
a|b |
abdabd |
ab\ab |
匹配字符a或b,如果a出现在b前,优先匹配a |
|
() |
|
|
括号内的表达式也表示一个组 |
|
[…] |
ww...ff |
3处匹配 |
匹配字符组中的字符 |
|
[^…] |
w=.f |
W=f |
匹配除了字符组中字符的所有字符 |
|
\b(a\b) |
assda |
a |
匹配一个单词的结尾 |
三、字符组
字符组:[字符组]
内容:匹配的是一个字符的内容
字符组内的范围都是根据ascii码来排序
在同一个位置可能出现的各种字符组成一个字符组,在正则表达式中用[]表示,字符分为很多类,比例数字、字母、标点等
|
正则表达式 |
待匹配字符 |
匹配结果 |
说明 |
|
[123456789] |
8 |
8 |
在一个字符组里枚举合法的所有字符,字符组里的任意一个字符和‘待匹配字符’相同都视为可以匹配 |
|
[123456789] |
a |
(没有匹配) |
待匹配字符不在字符组中 |
|
[1-9] |
8 |
8 |
[1-9]和[123456789]的表达结果相同 |
|
[a-z] |
s |
s |
如果要匹配所有小写字母可用[a-z] |
|
[A-Z] |
WE |
WE |
[A-Z]表示所有大写字母 |
|
[1-9a-z-A-Z] |
1Dc |
1Dc |
匹配数字1-9,大小写a-z,用来验证十六位进制 |
|
[\-] |
- |
- |
在字符组中-是有特殊意义的,需要用\来转义 |
|
[A-Z0-9a-z_] 零 |
_ |
_ |
在字符组中匹配下划线 |
|
[\D\d] |
所有 |
所有 |
匹配所有 |
|
[\W\w] |
所有 |
所有 |
匹配所有 |
|
[\S\s] |
所有 |
所有 |
匹配所有 |
四、量词
特点:表示匹配的次数 在量词的范围内尽可能的多匹配
|
正则表达式 |
待匹配字符 |
匹配结果 |
说明 |
|
* |
|
|
重复零次或更多次 |
|
+ |
|
|
重复一次或多次 |
|
? |
|
|
重复零次或一次 |
|
{n} |
|
|
重复n次 |
|
{n,} |
|
|
重复n次或更多次 |
|
{n,m} |
|
|
重复n次到m次 |
五、常用用法
.^$用法
|
正则表达式 |
待匹配字符 |
匹配结果 |
说明 |
|
海. |
海燕海角海东 |
海燕\海角\海东 |
重复零次或更多次 |
|
海.$ |
海燕海角海东 |
海东 |
只匹配结尾海.$ |
|
^海. |
海燕海角海东 |
海燕 |
只匹配开头海^海. |
*+?{}用法 注意:前面的*、+、?、{}都是贪婪匹配也就是尽可能匹配,在后面加?,使其变为惰性匹配
|
正则表达式 |
待匹配字符 |
匹配结果 |
说明 |
|
李.* |
李杰和李莲英和李大管 |
李杰和李莲英和李大管 |
*重复零次或更多次,匹配李后面零个或多个字符 |
|
李.+ |
李杰和李莲英和李大管 |
李杰和李莲英和李大管 |
+重复一次或多次,匹配李后面一个或多个字符 |
|
李.? |
李杰和李莲英和李大管 |
李杰\李莲\李大 |
?重复零次或一次,匹配李后面零个或一个字符 |
|
李.{1,2} |
李杰和李莲英和李大管 |
李杰和\李莲英\李大管 |
{1,2}匹配一次到两次任意字符 |
|
李.{1,2}? |
李杰和李莲英和李大管 |
李杰\李莲\李大 |
惰性匹配 |
[] [^]用法
|
正则表达式 |
待匹配字符 |
匹配结果 |
说明 |
|
李[杰莲英大管]* |
李杰和李莲英和李大管 |
李杰李莲英李大管 |
匹配李字后面[杰莲英大管]字符,任意次 |
|
李[^和]* |
李杰和李莲英和李大管 |
李杰李莲英李大管 |
匹配一个不是和的字符任意次 |
|
[\d] |
12df34 |
1\2\3\4 |
任意匹配一个数字,匹配到4个结果 |
|
[\d]+ |
12df34 |
123\4 |
任意匹配一个数字,匹配到2个结果 |
分组()与或| [^]的用法
身份证号码是一个长度为15或18个字符的字符串,如果是15位则全都是由数字组成,首位不能位0;如果是18位则前17位全都是数字,末尾可能是数字或者字母x,下面我们尝试用正则来表示。
|
正则表达式 |
待匹配字符 |
匹配结果 |
说明 |
|
^[1-9]\d{13,16}[0-9x]$ |
110101198001017032 |
110101198001017032 |
表示可以匹配一个正确的身份证号 |
|
^[1-9]\d{13,16}[0-9x]$ |
1101011980010170 |
1101011980010170 |
表示也可以匹配这串数字,但这并不是一个正确的身份证号码,它是一个16位的数字 |
|
^[1-9]\d{14}(\d{2}[0-9x])?$ |
1101011980010170 |
False |
现在不会匹配错误的身份证号了 ()表示分组,将\d{2}[0-9x]分成一组,就可以整体约束他们出现的次数为0-1次 |
|
^([1-9]\d{16}[0-9x]|[1-9]\d{14})$ |
110105199812067023 |
110105199812067023 |
表示先匹配[1-9]\d{16}[0-9x]如果没有匹配上就匹配[1-9]\d{14} |
匹配一个整数或者小数:整数不能多个零组成
|
正则表达式 |
待匹配字符 |
匹配结果 |
说明 |
|
[1-9]\d*|0 |
123 |
123 |
匹配整数 |
|
\d+\.\d+ |
0.233 |
0.233 |
匹配小数 |
|
\d+\.\d+|([1-9]\d*|0) |
123或者0.233 |
123或者0.233 |
匹配一个整数或者小数, 默认贪婪匹配:永远把相对长的规则放在左侧 |
转义符 \ 用法:
在正则表达式中,有很多有特殊意义的是元字符,比如\n和\s等,如果要在正则中匹配正常的"\n"而不是"换行符"就需要对"\"进行转义,变成'\\'
在python中,无论是正则表达式,还是待匹配的内容,都是以字符串的形式出现的,在字符串中\也有特殊的含义,本身还需要转义。所以如
果匹配一次"\n",字符串中要写成'\\n',那么正则里就要写成"\\\\n",这样就太麻烦了。这个时候我们就用到了r'\n'这个概念,此时的正则是r'\\n'就可以了。
|
正则表达式 |
待匹配字符 |
匹配结果 |
说明 |
|
\n |
\n |
False |
因为在正则表达式中\是有特殊意义的字符,所以要匹配\n本身,用表达式\n无法匹配 |
|
\\n |
\n |
True |
转义\之后变成\\,即可匹配 |
|
"\\\\n" |
'\\n' |
True |
如果在python中,字符串中的'\'也需要转义,所以每一个字符串'\'又需要转义一次 |
|
r'\\n' |
r'\n' |
True |
在字符串之前加r,让整个字符串不转义 |
贪婪匹配:
贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配
|
正则表达式 |
待匹配字符 |
匹配结果 |
说明 |
|
<.*> |
<script>...<script> |
<script>...<script> |
默认为贪婪匹配模式,会匹配尽量长的字符串 |
|
<.*?> |
r'\d' |
<script> <script> |
加上?为将贪婪匹配模式转为非贪婪匹配模式,会匹配尽量短的字符串 |
几个常用的非贪婪匹配Pattern:
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
.*?的用法:
. 是任意字符
* 是取 0 至 无限长度
? 是非贪婪模式,和在一起就是 取尽量少的任意字符,一般不会这么单独写
.*?x 就是取前面任意长度的字符,直到一个x出现
|
正则表达式 |
待匹配字符 |
匹配结果 |
说明 |
|
. |
8as |
8as |
匹配除换行符以外的任意字符 |
|
\w |
A1_ |
A1_ |
匹配字母数字或下划线 |
|
\s |
|
|
匹配空白字符 |
|
\d |
123 |
123 |
匹配数字 |
|
\n |
|
|
匹配换行符 |
|
\t |
|
|
匹配制表符 |
|
^(^qw) |
qws |
qw |
匹配字符串的开始 |
|
$(we$) |
qwe |
we |
匹配字符串的结束 |
|
\W |
11s |
11 |
匹配非字母数字或下划线 |
|
\S |
11d |
11d |
匹非配空白字符 |
|
\D |
Sd1 |
Sd |
匹配非数字 |
|
a|b |
abdabd |
ab\ab |
匹配字符a或b,如果a出现在b前,优先匹配a |
|
() |
|
|
括号内的表达式也表示一个组 |
|
[…] |
ww...ff |
3处匹配 |
匹配字符组中的字符 |
|
[^…] |
w=.f |
W=f |
匹配除了字符组中字符的所有字符 |
|
\b(a\b) |
assda |
a |
匹配一个单词的结尾 |
re模块下的方法
import re #findall ret = re.findall('a', 'eva egon yuan') # 返回所有满足匹配条件的结果,放在列表里 print(ret) #['a', 'a'] #search().group() 碰到复合条件的对象就返回 ret = re.search('a', 'eva egon yuan').group() print(ret) # 'a' 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。 # match() ret = re.match('a', 'aaaabc').group() # 同search,在字符串开始处进行匹配,开头不匹配报错 print(ret) #a #split() ret = re.split('[ab]', 'abcd') # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割 print(ret) # ['', '', 'cd'] #sub() ret = re.sub('\d', 'H', 'eva3egon4yuan4', 1)#将数字替换成'H',参数1表示只替换1个 print(ret) #evaHegon4yuan4 #rsubn ret = re.subn('\d', 'H', 'eva3egon4yuan4')#将数字替换成'H',返回元组(替换的结果,替换了多少次) print(ret) #('evaHegonHyuanH', 3) #compile() obj = re.compile('\d{3}') #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字 ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串 print(ret.group()) #结果 : 123 #finditer().grounp() import re ret = re.finditer('\d', 'ds3sy4784a') #finditer返回一个存放匹配结果的迭代器 print(ret) # <callable_iterator object at 0x10195f940> print(next(ret).group()) #查看第一个结果 3 print(next(ret).group()) #查看第二个结果 4 print([i.group() for i in ret]) #查看剩余的左右结果 ['7', '8', '4']
import re ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com') print(ret) # ['oldboy'] 这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可 ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com') print(ret) # ['www.oldboy.com']
import re ret=re.split("\d+","eva3egon4yuan") print(ret) #['eva', 'egon', 'yuan'] ret=re.split("(\d+)","eva3egon4yuan") print(ret) #['eva', '3', 'egon', '4', 'yuan'] #在匹配部分加上()之后所切出的结果是不同的, #没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项, #这个在某些需要保留匹配部分的使用过程是非常重要的。
Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。
什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
import hashlib # 提供摘要算法的模块 md5 = hashlib.md5() md5.update(b'123456') print(md5.hexdigest()) # e10adc3949ba59abbe56e057f20f883e
不管算法多么不同,摘要的功能始终不变
对于相同的字符串使用同一个算法进行摘要,得到的值总是不变的
使用不同算法对相同的字符串进行摘要,得到的值应该不同
不管使用什么算法,hashlib的方式永远不变
#sha 算法 随着 算法复杂程度的增加 我摘要的时间成本空间成本都会增加 import hashlib sha1 = hashlib.sha1() sha1.update(bytes('中国','utf-8')) print(sha1.hexdigest()) #101806f57c322fb403a9788c4c24b79650d02e77
import hashlib usr = input('username :') pwd = input('password : ') with open('userinfo') as f: for line in f: user,passwd,role = line.split('|') md5 = hashlib.md5() md5.update(bytes(pwd,encoding='utf-8')) md5_pwd = md5.hexdigest() if usr == user and md5_pwd == passwd: print('登录成功') import hashlib with open('file','w',encoding='utf-8') as f: mima = '123' mima_1 = hashlib.md5() mima_1.update(bytes(mima,'utf-8')) mima_2 = mima_1.hexdigest() f.write('ale'+'|'+mima_2) username = input('请输入用户名:') userword = input('请输入密码:') with open('file', 'r', encoding='utf-8') as f: md5 = hashlib.md5() md5.update(bytes(userword,'utf-8')) md5_pwd = md5.hexdigest() for line in f: usr,pwd = line.split('|') if username == usr and md5_pwd == pwd: print('欢迎登陆') else: print('请重新输入~')
import hashlib # 提供摘要算法的模块 md5 = hashlib.md5(bytes('盐',encoding='utf-8')) # md5 = hashlib.md5() md5.update(b'123456') print(md5.hexdigest())
如果数据量很大,可以分块多次调用update(),最后计算的结果是一样的
import hashlib # md5 = hashlib.md5() # md5.update(bytes('这段内容很长','utf-8')) # print(md5.hexdigest()) #5206eb302722d79fffc36ddaf7ce6bc9 md5 = hashlib.md5() md5.update(bytes('这段内容','utf-8')) md5.update(bytes('很长','utf-8')) print(md5.hexdigest()) #5206eb302722d79fffc36ddaf7ce6bc9
[user] user_name = Mr L password = 222 isremember = True [connect] ip = 127.0.0.1 port = 4723 [hp] [dida] green = read bluwe = tian [remark] info = ok [people] teacher = kkk sudent = sx
#configparser初始化 连接以下代码 import configparser # 生成ConfigParser对象 config = configparser.ConfigParser() ## 读取配置文件 filename = 'config.ini' config.read(filename, encoding='utf-8')
all_sections = config.sections() print('sections: ', all_sections) #sections: ['user', 'connect']
items = config.items('user') print(items) #[('user_name', "'Mr,X'"), ('password', "'222'")]
options = config.options('user') print(options) #['user_name', 'password']
# config.get() name = config.get('user', 'user_name') print(name, type(name)) #'Mr,X' <class 'str'> #config.getint() port = config.getint('connect', 'port') print(port, type(port)) # 4723 <class 'int'> #config.getflaot() port = config.getfloat('connect','port') print(port,type(port)) #4723.0 <class 'float'>
# 检查section是否存在 print(config.has_section('user')) #True print(config.has_section('connect')) #True # 检查option是否存在 print(config.has_option('user','user_name')) #True print(config.has_option('user','name')) #False
if not config.has_section('people'): config.add_section('people') config.set('people','teacher','ale') config.set('people','teacher','kkk') config.set('people','sudent','sx') config.write(open(filename,'w')) mark = config.items('people') print(mark)
config.remove_section('people') all_section = config.sections() config.write(open(filename,'w')) #文件这样操作才能使文件中的'people'删除 print(all_section) #['user', 'connect', 'hp', 'dida', 'remark']
config.remove_option('hp','are') all_option = config.options('hp') config.write(open(filename,'w')) #文件这样操作才能使文件中的'hp'删除 print(all_option)
#对configparser对象执行的一些修改操作,必须重新写回到文件才可生效 '''对配置文件的操作''' config.write(open(filename,'w'))
logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;
相比print(),具备如下优点:
1).可以通过设置不同的日志等级,在release版本中只输出重要信息,而不必显示大量的调试信息;
2).print()将所有信息都输出到标准输出中,严重影响开发者从标准输出中查看其它数据;logging则可以由开发者决定将信息输出到什么地方,以及怎么输出
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 默认情况下python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说 明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET) 默认的日志格式为日志级别:Logger名称:用户输出消息。
日志等级
| 等级 | 介绍 | 数值 |
| CRITICAL | 当发生严重错误,导致应用程序不能继续运行时记录的信息 | 50 |
| ERROR | 由于一个更严重的问题导致某些功能不能正常运行时记录的信息 | 40 |
| WARNING | 当某些不期望的事情发生时记录的信息(如,磁盘可用空间较低),但是此时应用程序还是正常运行的 | 30 |
| INFO | 信息详细程度仅次于DEBUG,通常只记录关键节点信息,用于确认一切都是按照我们预期的那样进行工作 | 20 |
| DEBUG | 打印全部的日志,详细的信息,通常只出现在诊断问题上 | 10 |
| NOTSET | 如果需要显示低于WARNING级别的内容,可以引入NOTSET级别来显示 | 0 |
日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET
|
||
上面列表中的日志等级是从上到下依次升高的,即:DEBUG < INFO < WARNING < ERROR < CRITICAL,而日志的信息量是依次减少的
logging模块提供了两种记录日志的方式:第一种方式是使用logging提供的模块级别的函数,第二种方式是使用Logging日志系统的四大组件
logging模块定义的模块级别的常用函数
| 函数 | 说明 |
| logging.debug(msg, *args, **kwargs) | 创建一条严重级别为DEBUG的日志记录 |
| logging.info(msg, *args, **kwargs) | 创建一条严重级别为INFO的日志记录 |
| logging.warning(msg, *args, **kwargs) | 创建一条严重级别为WARNING的日志记录 |
| logging.error(msg, *args, **kwargs) | 创建一条严重级别为ERROR的日志记录 |
| logging.critical(msg, *args, **kwargs) | 创建一条严重级别为CRITICAL的日志记录 |
| logging.log(level, *args, **kwargs) | 创建一条严重级别为level的日志记录 |
| logging.basicConfig(**kwargs) | 对root logger进行一次性配置 |
| 其中logging.basicConfig(**kwargs)函数用于指定“要记录的日志级别”、“日志格式”、“日志输出位置”、“日志文件的打开模式”等信息,其他几个都是用于记录各个级别日志的函数。 | |
import logging LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s" DATE_FORMAT = "%m-%d-%Y %H:%M:%S %p" logging.basicConfig(level=logging.DEBUG,filename='my.log',datefmt=DATE_FORMAT,format=LOG_FORMAT) #从debug输出 logging.debug('this is a debug!....') logging.info('this is a info!....') logging.warning('this is a warning!....') logging.error('this is a error!....') logging.critical('this is a critical!....') #my.log中: # 05-24-2018 00:08:04 AM - DEBUG - this is a debug!.... # 05-24-2018 00:08:04 AM - INFO - this is a info!.... # 05-24-2018 00:08:04 AM - WARNING - this is a warning!.... # 05-24-2018 00:08:04 AM - ERROR - this is a error!.... # 05-24-2018 00:08:04 AM - CRITICAL - this is a critical!....
logging模块的四大组件
| loggers | 提供应用程序代码直接使用的接口 |
| handlers | 用于将日志记录发送到指定的目的位置 |
| filters | 提供更细粒度的日志过滤功能,用于决定哪些日志记录将会被输出(其它的日志记录将会被忽略) |
| formatters | 用于控制日志信息的最终输出格式 |
使用logging提供的模块级别的函数记录日志
可以通过logging模块定义的模块级别的方法去完成简单的日志记录
只有级别大于或等于日志记录器指定级别的日志记录才会被输出,小于该级别的日志记录将会被丢弃
import logging LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s" DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p" logging.basicConfig(level=logging.DEBUG) #从debug输出 # logging模块提供的日志记录函数所使用的日志器设置的日志级别是WARNING # 提高了logging的日志级别到DEBUG # 调用一下basicConfig()方法,设置想要的内容以参数的形式传递进去(修改默认参数) logging.log(logging.DEBUG,'this is a debug!....') logging.log(logging.INFO,'this is a info!....') logging.log(logging.WARNING,'this is a warning!....') logging.log(logging.ERROR,'this is a error!....') logging.log(logging.CRITICAL,'this is a critical!....') # 输出: # DEBUG:root:this is a debug!.... # INFO:root:this is a info!.... # WARNING:root:this is a warning!.... # ERROR:root:this is a error!.... # CRITICAL:root:this is a critical!....
import logging LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s" DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p" # logging.basicConfig(level=logging.DEBUG) #从debug输出 默认日志级别是WARNING logging.log(logging.DEBUG,'this is a debug!....') logging.log(logging.INFO,'this is a info!....') logging.log(logging.WARNING,'this is a warning!....') logging.log(logging.ERROR,'this is a error!....') logging.log(logging.CRITICAL,'this is a critical!....') #输出 # WARNING:root:this is a warning!.... # ERROR:root:this is a error!.... # CRITICAL:root:this is a critical!....
WARNING:root:this is a warning!.... 日志级别;日志名字;日志内容 logging模块提供的日志记录函数所使用的日志器设置的日志格式默认是BASIC_FORMAT,其值为: "%(levelname)s:%(name)s:%(message)s"
# 该方法用于为logging日志系统做一些基本配置,方法定义如下: # logging.basicConfig(**kwargs) # 函数名称 描述 # filename 指定日志输出目标文件的文件名,指定该设置项后日志信心就不会被输出到控制台了 # filemode 指定日志文件的打开模式,默认为'a'。需要注意的是,该选项要在filename指定时才有效 # format 指定日志格式字符串,即指定日志输出时所包含的字段信息以及它们的顺序。logging模块定义的格式字段下面会列出 # datefmt 指定日期/时间格式。需要注意的是,该选项要在format中包含时间字段%(asctime)s时才有效 # level 指定日志器的日志级别stream指定日志输出目标stream,如sys.stdout、sys.stderr以及网络 # stream 需要说明的是,stream和filename不能同时提供,否则会引发 ValueError异常 # style Python 3.2中新添加的配置项。指定format格式字符串的风格,可取值为'%'、'{'和'$',默认为'%' # handlersPython 3.3中新添加的配置项。该选项如果被指定,它应该是一个创建了多个Handler的可迭代对象,这些handler将会被添加到root logger # 需要说明的是:filename、stream和handlers这三个配置项只能有一个存在,不能同时出现2个或3个,否则会引发ValueError异常。
# 我们来列举一下logging模块中定义好的可以用于format格式字符串中字段有哪些: 字段\属性名称 使用格式 描述 asctime %(asctime)s 日志事件发生的时间--人类可读时间,如:2003-07-08 16:49:45,896 created %(created)f 日志事件发生的时间--时间戳,就是当时调用time.time()函数返回的值 relativeCreated %(relativeCreated)d 日志事件发生的时间相对于logging模块加载时间的相对毫秒数(目前还不知道干嘛用的) msecs %(msecs)d 日志事件发生事件的毫秒部分levelname%(levelname)s该日志记录的文字形式的日志级别('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL') levelno %(levelno)s 该日志记录的数字形式的日志级别(10, 20, 30, 40, 50) name %(name)s 所使用的日志器名称,默认是'root',因为默认使用的是 rootLogger message %(message)s 日志记录的文本内容,通过 msg % args计算得到的 pathname %(pathname)s 调用日志记录函数的源码文件的全路径 filename %(filename) pathname的文件名部分,包含文件后缀 module %(module)s filename的名称部分,不包含后缀 lineno %(lineno)d 调用日志记录函数的源代码所在的行号 funcName %(funcName)s 调用日志记录函数的函数名 process %(process)d 进程ID processName %(processName)s 进程名称,Python 3.1新增 thread %(thread)d 线程ID threadName %(thread)s 线程名称
logging.basicConfig()函数是一个一次性的简单配置工具,也就是说只有在第一次调用该函数时会起作用,后续再次调用该函数时完全不会产生任何操作的,多次调用的设置并不是累加操作。
exc_info: 其值为布尔值,如果该参数的值设置为True,则会将异常异常信息添加到日志消息中。如果没有异常信息则添加None到日志信息中。
stack_info: 其值也为布尔值,默认值为False。如果该参数的值设置为True,栈信息将会被添加到日志信息中。
extra: 这是一个字典(dict)参数,它可以用来自定义消息格式中所包含的字段,但是它的key不能与logging模块定义的字段冲突
import logging file_handler = logging.FileHandler(filename='x1.log', mode='a', encoding='utf-8',) #输出位置 logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', #日志格式 datefmt='%Y-%m-%d %H:%M:%S %p', handlers=[file_handler,], level=logging.ERROR #日志等级 ) logging.error('你好')
import time import logging from logging import handlers sh = logging.StreamHandler() rh = handlers.RotatingFileHandler('myapp.log', maxBytes=1024,backupCount=5) fh = handlers.TimedRotatingFileHandler(filename='x2.log', when='s', interval=5, encoding='utf-8') logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', handlers=[fh,sh,rh], level=logging.ERROR ) for i in range(1,100000): time.sleep(1) logging.error('KeyboardInterrupt error %s'%str(i))
import logging logger = logging.getLogger() fh = logging.FileHandler('test.log',encoding='utf-8') # 创建一个handler,用于写入日志文件 ch = logging.StreamHandler() # 再创建一个handler,用于输出到控制台 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setLevel(logging.DEBUG) fh.setFormatter(formatter) ch.setFormatter(formatter) logger.addHandler(fh) #logger对象可以添加多个fh和ch对象 logger.addHandler(ch) logger.debug('logger debug message') logger.info('logger info message') logger.warning('logger warning message') logger.error('logger error message') logger.critical('logger critical message') #输出: # 2019-09-10 21:36:41,471 - root - WARNING - logger warning message # 2019-09-10 21:36:41,471 - root - ERROR - logger error message # 2019-09-10 21:36:41,471 - root - CRITICAL - logger critical message

浙公网安备 33010602011771号