Python module和包的总结
模块:为了编写可维护的代码,我们将很多函数分组,分别放到不同的文件里,这样,代码的可利用率提高,代码量减少。在python中,一个 .py文件就称之为一个模块(module)。
模块有以下几种方式:
a.python标准库
b.第三方模块
c.引用程序自定义模块
引入模块方式:
1、import 模块名1,模块名2(调用:模块名1.函数名)
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 def add(x, y): 6 return x+y 7 8 9 def sub(x, y): 10 return x-y
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import cal 4 5 6 print(cal.add(3, 5))
2、from 模块名1 import 函数名(调用:函数名)
#!/usr/bin/env python # -*- coding:utf-8 -*- def add(x, y): return x+y def sub(x, y): return x-y
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 from cal import add # 只引入一个函数 4 from cal import * # 引入多个函数 5 6 7 print(add(3, 5))
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import sys # 引入标准库 4 print(sys.path) # 查看当前路径 5 6 from my_module import cal # 引入自定义库,在当前路径的下一层 7 from my_module.module1.module2 import cal # 引入自定义库,多级目录 8 print(cal.add(3, 2))
•time模块
在python中,通常有这几种方式来表示时间:
a.时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型
b. 格式化的时间字符串
c.元祖(struct_time):struct_time元祖共有9个元素(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import time 4 5 # 时间戳,用于计算 6 print(time.time()) # 1548861231.773613秒,从1970年1月1日 00:00:00开始计算 7 # 结构化时间,当地时间 8 print(time.localtime()) # time.struct_time(tm_year=2019, tm_mon=1, tm_mday=30, tm_hour=23, tm_min=18, tm_sec=52, tm_wday=2, tm_yday=30, tm_isdst=0) 9 t = time.localtime() 10 print(t.tm_year) # 获取当前年份 11 print(t.tm_mday) # 获取当前月的第多少天 12 print(t.tm_wday) # 获取这周第几天,默认从0-6 13 # 结构化时间,标准时间--utc 14 print(time.gmtime()) # 世界标准时间,英国;time.struct_time(tm_year=2019, tm_mon=1, tm_mday=30, tm_hour=15, tm_min=26, tm_sec=17, tm_wday=2, tm_yday=30, tm_isdst=0) 15 ''' 16 struct_time ---> timestamp:mktime 17 timestamp ---> struct_time:localtime/gmtime 18 struct_time ---> format string:strftime 19 format string ---> struct_time:strptime 20 strptime:把一个格式化时间字符串转换为struct_time。实际上它和strftime()是逆操作 21 %y:年 22 %m:月 23 %d:日 24 %x:时分秒 25 ''' 26 # ----将结构化时间转换成时间戳 27 print(time.mktime(time.localtime())) 28 # ----将结构化时间转成字符串时间 29 print(time.strftime("%y-%m-%d %x", time.localtime())) 30 # ----将字符串时间转成结构化时间 31 print(time.strptime("2019:01:30:23:53:59", "%y:%m:%d:%x")) 32 33 print(time.asctime()) # wed jan 30 23:56:16 2019 34 print(time.ctime()) # wed jan 30 23:57:09 2019 35 ''' 36 time.sleep(3):线程推迟指定的时间运行,单位为秒 37 time.clock(): 38 a.unix系统上,他返回的是“进程时间”,它是用秒表示的浮点数 39 b.windows中,第一次调用,返回的是进程运行的实际时间;第二次之后的调用时第一次调用以后到现在运行的时间,即时间差 40 ''' 41 42 43 import datetime 44 print(datetime.datetime.now()) # 2019-01-31 00:04:25.944866
•random模块
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import random 4 print(random.random()) # 0-1之间的随机数 5 print(random.randint(1, 10)) # 自定义范围的整形 6 print(random.randrange(1, 5)) # 自定义范围,第二个数取不到 7 print(random.choice([11, 12, 13, 14, 15])) 8 print(random.sample([11, 12, 13, 14, 15], 2)) # 指定一个列表,并指定随机产生的个数 9 print(random.uniform(1, 3)) # 取任意范围的float 10 item = [1, 3, 5, 7, 9] 11 random.shuffle(item) # 打乱集合中的顺序 12 print(item)
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import random 4 5 6 def v_code(): 7 res = "" 8 for i in range(5): 9 num = random.randint(0, 9) 10 alf = chr(random.randint(65, 122)) 11 s = str(random.choice([num, alf])) 12 res += s 13 return res 14 15 16 print(v_code()) # 25ze5
•os模块
os模块是与操作系统交互的一个接口
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import os 4 print(os.getcwd()) # 获取当前工作目录,即当前python脚本工作的目录路径 5 # print(os.chdir("dirname")) # 改变当前脚本工作目录,相当于shell下cd 6 print(os.curdir) # 返回当前目录:('.') 7 print(os.pardir) # 获取当前目录的父目录字符串名:('..') 8 print(os.makedirs('dirname1/dirname2')) # 可生成多层递归目录 9 print(os.removedirs('dirname')) # 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,以此类推 10 print(os.mkdir('dirname')) # 生成单级目录,相当于shell中 mkdir dirname 11 print(os.rmdir('dirname')) # 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname 12 print(os.listdir('dirname')) # 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 13 print(os.remove('dirname')) # 删除一个文件 14 print(os.rename('oldname', 'newname')) # 重命名文件/目录 15 print(os.stat('path/filename')) # 获取文件/目录信息 16 print(os.sep) # 输出操作系统特定的路径分隔符,win下为'\\',linux下为'\' 17 print(os.linesep) # 输出当前平台使用的行终止符,win下为'\r\n',linux下为'\n' 18 print(os.pathsep) # 输出用于分割文件路径的字符串win下为';',linux下为': ' 19 print(os.name) # 输出字符串指定当前使用平台。win下为'nt',linux下为'posix' 20 print(os.system('bash command')) # 运行shell命令,直接显示 21 print(os.environ) # 获取系统环境变量 22 print(os.path.abspath('path')) # 返回path规范化的绝对路径 23 print(os.path.split('path')) # 将path分割成目录和文件名二元祖返回 24 print(os.path.dirname('path')) # 返回path目录,其实就是os.path.split('path') 的第一个元素 25 print(os.path.basename('path')) # 返回path最后的文件名。 26 print(os.path.exists('path')) # 如果path存在,返回true;反之则false 27 print(os.path.isabs('path')) # 如果path是绝对路径,返回true 28 print(os.path.isdir('path')) # 如果path是一个存在的目录,则返回true,反之则false 29 print(os.path.join('path1', 'path2')) # 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 30 print(os.path.getatime('path')) # 返回path所指向的文件或目录的最后存取时间 31 print(os.path.getmtime('path')) # 返回path所指向的文件或目录的最后修改时间
•sys模块
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import sys 4 print(sys.argv) # 命令行参数list,第一个元素是程序本身路径 5 print(sys.exit('n')) # 退出程序,正常退出时exit(0) 6 print(sys.version) # 获取python解释程序的版本信息 7 print(sys.path) # 返回模块的搜索路径,初始化时使用pythonpath环境变量的值 8 print(sys.platform) # 返回操作系统平台名称
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import sys,time 4 for i in range(100): 5 sys.stdout.write('#') 6 time.sleep(0.1) # 睡眠0.1秒 7 sys.stdout.flush() # 刷新缓存
•json & pickle 模块
之前学习过的python内置函数eval方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时候,eval就不管用了,所以eval的重点还是通常用来执行一个字符串表达式,并返回表达式的值。
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import json 4 # x = "[null,true,false,1]" 5 # # print(eval(x)) # 报错 6 # print(json.loads(x)) # [none, true, false, 1] 7 dic = {"name": "alex"} 8 f = open("hello", "w") 9 dic_str = json.dumps(dic) 10 f.write(dic_str) # 等价于 json.dump(dic,f),一般用于文件操作
1 # import pickle 2 # dic = {'name': 'alex', 'age': 23, 'sex': 'male'} 3 # print(type(dic)) # <class 'dict'> 4 # j = pickle.dumps(dic) 5 # print(type(j)) # <class 'bytes'> 6 # f = open('序列化对象_pickle', 'wb') # 注意是w是写入str,wb是写入bytes,j是'bytes' 7 # f.write(j) # 等价于 pickle.dump(dic,j) 8 # f.close() 9 10 # -------反序列化 11 import pickle 12 f = open('序列化对象_pickle', 'rb') 13 data = pickle.loads(f.read()) # 等价于 data = pickle.load(f) 14 print(data['name'])
什么是序列化?
我们把对象(变量)从内存中编程可存储或传输的过程称之为序列化,在python中叫pickling,在其他语言中也被称为serialization,marshalling,flattening等等,都是一个意思。
序列化之后,就可以把序列化后的内存写入磁盘,或者通过网络传输到别的机器上。
反过来,把变量内存从序列化的对象重新读到内存里称之为反序列化,即unpickling。
json
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如xml,但更好的方法是序列化未json,因为json表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。json不仅是标准格式,并且比xml更快,而且可以直接在web页面中读取,非常方便。
•xml模块
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,以前在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml。
xml的格式如下,就是通过<>节点来区别数据结构的:
1 <?xml version ="1.0" ?> 2 <date> 3 <country name="liechtenstein"> 4 <rank updated="yes">2</rank> 5 <year>2008</year> 6 <gdppc>141100</gdppc> 7 <neighbor name="austria" direction="e"/> 8 <neighbor name="switzerland" direction="w"/> 9 </country> 10 </date>
xml协议在各个语言里的都是支持的,在python中可以用以下模块操作xml:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import xml.etree.elementtree as et 4 5 tree = et.parse("xml_lesson") # 调用et下的parse解析这个xml文件,拿到的对象赋值给tree 6 root = tree.getroot() 7 print(root.tag) 8 9 # 遍历xml文档 10 for child in root: 11 print(child.tag, child.attrib) # child.attrib:获取节点属性 12 for i in child: 13 print(i.tag, i.attrib, i.text) 14 15 # 只遍历year节点 16 for node in root.iter('rank'): # 遍历root根节点下的iter某一节点的“rank” 17 print(node.tag, node.text) 18 19 # 修改 20 for node_update in root.iter('rank'): 21 new_rank = int(node_update.text) + 1 22 node_update.text = str(new_rank) 23 node_update.set('updated', 'no') # 设置他的标签值 24 25 tree.write('xml_lesson') # 将内存中的数据重新写入进去 26 27 # 删除node 28 for country in root.findall('country'): 29 rank = int(country.find('rank').text) 30 if rank == 5: 31 root.remove(country) 32 33 tree.write('xml_lesson')
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import xml.etree.elementtree as et 4 new_xml = et.element("namelist") # 创建根节点 5 name = et.subelement(new_xml, "name", attrib={"enrooled": "yes"}) 6 age = et.subelement(name, "age", attrib={"checked": "no"}) 7 sex = et.subelement(name, "sex") 8 sex.text = '33' 9 name2 = et.subelement(new_xml, "name", attrib={"enrolled": "no"}) 10 age = et.subelement(name2, "age") 11 age.text = '19' 12 13 et = et.elementtree(new_xml) # 生成文档对象 14 et.write("xml_test.xml", encoding="utf-8", xml_declaration=true) 15 16 et.dump(new_xml) # 打印生成的格式 17 18 # =========以下为xml创建效果===== 19 <?xml version='1.0' encoding='utf-8'?> 20 <namelist> 21 <name enrooled="yes"> 22 <age checked="no" /> 23 <sex>33</sex> 24 </name> 25 <name enrolled="no"> 26 <age>19</age> 27 </name> 28 </namelist>
•re模块
正则表达式(或re)是一种小型的、高度专业化的编程语言,(python)它内嵌在python中,并通过re模块实现。正则表达式模式被编译成一系列的字节码,然后由用c编写的匹配引擎执行。
字符匹配(普通字符,元字符):
普通字符 >>>re.findall('alex', 'zhangsanalexlisi')
['alex']
元字符:.、^、$、*、+、?、{}、[]、|、()、\
.:匹配任意字符,除\n之外
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall('alex', 'zhangsanalexlisi')) # ['alex'] 5 print(re.findall('a..x', 'zhangsanalexlisi')) # ['alex']
^:必须将“^”放在字符串开头位置,判断字符串以xxx开头,返回布尔值,如果以xxx开头,返回“真”,反之则“假”
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall('^alex', 'zhangsanalexlisi')) # [] 5 print(re.findall('^alex', 'alexzhangsanlisi')) # ['alex'] 6 print(re.findall('^a..x', 'zhangsanalexlisi')) # [] 7 print(re.findall('^a..x', 'alexzhangsanlisi')) # ['alex']
$:必须将“$”放在字符串结尾位置,判断字符串以xxx结尾,返回布尔值,如果以xxx结尾,返回“真”,反之则“假”
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall('alex$', 'zhangsanalexlisi')) # [] 5 print(re.findall('alex$', 'zhangsanlisialex')) # ['alex'] 6 print(re.findall('^alex$', 'zhangsanalexlisi')) # [] 7 print(re.findall('^alex$', 'alex')) # ['alex'] 8 print(re.findall('a..x$', 'zhangsanalexlisi')) # [] 9 print(re.findall('a..x$', 'zhangsanlisialex')) # ['alex'] 10 print(re.findall('^a..x$', 'zhangsanlisialex')) # [''] 11 print(re.findall('^a..x$', 'alex')) # ['alex']
*、+、?、{}:以x重复出现
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 # *:范围(0,无穷) 5 print(re.findall('d*', 'zhangsanddddddalexlisi')) # ['', '', '', '', '', '', '', '', 'dddddd', '', '', '', '', '', '', '', '', ''] 6 7 8 # +:范围(1,无穷) 9 print(re.findall('d+', 'zhangsanddddddalexlisi')) # ['dddddd'] 10 11 12 # *与+区别: 13 print(re.findall('alex*', 'asdfgalex')) # ['alex'] 14 print(re.findall('alex+', 'asdfgalex')) # ['alex'] 15 print(re.findall('alex*', 'asdfgale')) # ['ale'] 16 print(re.findall('alex+', 'asdfgale')) # [] 17 18 19 # ?:范围(0,1) 20 print(re.findall('alex?', 'asdfgale')) # ['ale'] 21 print(re.findall('alex?', 'asdfgalex')) # ['alex'] 22 23 24 # *与?共用:以最小匹配0次 25 print(re.findall('alex*?', 'asdfgale')) # ['ale'] 26 print(re.findall('alex*?', 'asdfgalexxxx')) # ['ale'] 27 28 29 # +与?共用:以最小匹配1次 30 print(re.findall('alex+?', 'asdfgale')) # [] 31 print(re.findall('alex+?', 'asdfgalexxxx')) # ['alex'] 32 33 34 # {}: 给定一个范围 35 # {0,无穷}==>* 36 # {1,无穷}==>+ 37 # {0,1} ==>? 38 # {6}:出现6次 39 # {1,6}:出现1至6任意一个次数 40 print(re.findall('alex{6}', 'asdfgalex')) # [] 41 print(re.findall('alex{6}', 'asdfgalexxxxxx')) # ['alexxxxxx'] 42 print(re.findall('alex{1,6}', 'asdfgalexxx')) # ['alexxx'] 43 print(re.findall('alex{1,6}', 'asdfgalexxxxxx')) # ['alexxxxxx']
[]:中间出现的全部为普通字符;相当于“或”;只匹配一个;表示范围
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 5 # []字符串:中间出现的全部为普通字符;相当于“或”;只匹配一个;表示范围 6 print(re.findall('x[y]', 'abcx')) # [] 7 print(re.findall('x[y]', 'abcxy')) # ['xy'] 8 9 10 # 中间出现:* 11 print(re.findall('x[y*]', 'abcx')) # [] 12 print(re.findall('x[y*]', 'abcxy')) # ['xy'] 13 print(re.findall('x[y*]', 'abcx*')) # ['x*'] 14 15 16 # 中间出现:-;范围不允许a-z,只能a-z或者a-z 17 print(re.findall('a[a-z]', 'a2bcdefghijklmnopqrxtuvwxyzabcdefghijklmnopqrstuvwxyz')) # [] 18 print(re.findall('a[a-z]', 'abcdefghijklmnopqrxtuvwxyzabcdefghijklmnopqrstuvwxyz')) # ['ab'] 19 print(re.findall('a[a-z]', 'a2bcdefghijklmnopqrxtuvwxyzabcdefghijklmnopqrstuvwxyz')) # [] 20 print(re.findall('a[a-z]', 'aabcdefghijklmnopqrxtuvwxyzabcdefghijklmnopqrstuvwxyz')) # ['aa'] 21 22 23 # 后面在出现一个:* 24 print(re.findall('a[a-z]*', 'a2bcdefghijklmnopqrxtuvwxyzabcdefghijklmnopqrstuvwxyz')) # ['a'] 25 print(re.findall('a[a-z]*', 'abcdefghijklmnopqrxtuvwxyzabcdefghijklmnopqrstuvwxyz')) # ['abcdefghijklmnopqrxtuvwxyz'] 26 print(re.findall('a[a-z]*', 'abcdefghijklmnopqrxtuvwxyzabcdefghijklmnopqrstuvwxyz9')) # ['abcdefghijklmnopqrxtuvwxyz'] 27 28 29 # 中间出现:^;代表“非” 30 print(re.findall('q[^a-z]', 'qabc')) # [] 31 print(re.findall('q[^a-z]', 'q12')) # ['q1']
|:“或”的意思,要么左边,要么右边
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall(r'ka|b', 'sdfgjkabc')) # ['ka', 'b'] 5 print(re.findall(r'ka|b', 'sdfgjkac')) # ['ka'] 6 print(re.findall(r'ka|b', 'sdfgjkbc')) # ['b']
():分组,代表一个整体
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall('(abc)', 'abcabcabc')) # ['abc', 'abc', 'abc'] 5 print(re.search('\d', 'dfas25fd35')) # <re.match object; span=(4, 5), match='2'> 6 print(re.search('\d', 'dfas25fd35').group()) # 2 7 print(re.search('\d+', 'dfas25fd35')) # <re.match object; span=(4, 6), match='25'> 8 print(re.search('\d+', 'dfas25fd35').group()) # 25 9 print(re.search('\d{3}', 'dfas25fd35')) # none 10 print(re.search('(?p<name>[a-z]+)', 'alex28liming33')) # <re.match object; span=(0, 4), match='alex'> 11 print(re.search('(?p<name>[a-z]+)', 'alex28liming33').group()) # alex 12 print(re.search('(?p<name>[a-z]+)\d+', 'alex28liming33')) # <re.match object; span=(0, 6), match='alex28'> 13 print(re.search('(?p<name>[a-z]+)\d+', 'alex28liming33').group()) # alex28 14 print(re.search('(?p<name>[a-z]+)\d+', 'alex28liming33').group('name')) # alex
\:转义符
反斜杠后面跟元字符去除特殊功能
反斜杠后面跟普通字符实现特殊功能
\d:匹配任何十进制数;相当于[0-9]
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall('\d', '12+(34*6+2-5*(2-1))')) # ['1', '2', '3', '4', '6', '2', '5', '2', '1'] 5 print(re.findall('\d+', '12+(34*6+2-5*(2-1))')) # ['12', '34', '6', '2', '5', '2', '1']
\d:匹配任何非十进制数;相当于[^0-9]
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall('\d', '12+(34*6+2-5*(2-1))')) # ['+', '(', '*', '+', '-', '*', '(', '-', ')', ')'] 5 print(re.findall('\d+', '12+(34*6+2-5*(2-1))')) # ['+(', '*', '+', '-', '*(', '-', '))']
\s:匹配任何空白字符;相当于[\t\n\r\f\v]
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 5 # 转义符:\ 6 print(re.findall('\s', 'hello word!')) # [' ']
\s:匹配任何非空白字符;相当于[^\t\n\r\f\v]
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 5 print(re.findall('\s', 'hello word!')) # ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'd', '!'] 6 print(re.findall('\s+', 'hello word!')) # ['hello', 'word!']
\w:匹配任何字母数字字符;相当于[a-za-z0-9]
\w:匹配任何非字母数字字符;相当于[^a-za-z0-9]
\b:匹配任何一个特殊字符边界,如:空格、&、#等
re模块下的常用方法
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 # 1 5 print(re.findall('a', 'alex lisi')) # ['a'];返回所有满足匹配条件的结果,放到列表里 6 7 8 # 2 9 print(re.search('a', 'alex lisi').group()) # a;函数在字符串内查找模式匹配,只能找到第一个匹配然后返回一个包;通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回node 10 11 12 # 3 13 print(re.match('a', 'zabc')) # none;同search(),仅匹配字符串开始处 14 15 16 # 4 17 print(re.split(' ', 'hello word abc')) # ['hello', 'word', 'abc'] 18 19 20 # 5 21 print(re.sub('\d+', 'a', 'alex6jack5', 1)) # alexajack5 22 print(re.subn('\d+', 'a', 'alex6jack5', 1)) # ('alexajack5', 1) 23 24 25 # 6 26 com = re.compile('\d{3}') 27 print(com.search('abc123de45').group()) # 123;可以多次调用 28 29 # 7 30 ret = re.finditer("\d+", "ab35cde47fg88") 31 print(ret) # <callable_iterator object at 0x00000028e5a765c0> 32 print(next(ret).group()) # 35 33 print(next(ret).group()) # 47 34 print(next(ret).group()) # 88
re补充:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall('www\.(baidu|sina)\.com', 'www.baidu.com')) # ['baidu'];优先匹配分组的内容 5 6 # 分组中添加‘?:’去除优先级 7 print(re.findall('www\.(?:baidu|sina)\.com', 'www.baidu.com')) # ['www.baidu.com']
•logging模块
一(简单引用)
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import logging 4 logging.debug('debug message') 5 logging.info('info message') 6 logging.warning('warning message') # warning:root:warning message 7 logging.error('error message') # error:root:error message 8 logging.critical('critical message') # critical:root:critical message
可见,默认情况下python和logging模块将日志打印到了标准输出中,且只显示了大于等于warning级别的日志,这说明默认的日志级别设置为warning(日志级别登记critical>error>warning>info>debug>notset),默认的日志格式为日志级别,logging名称:用户输出消息。
二 灵活配置日志级别,日志格式,输出位置
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import logging 4 5 logging.basicconfig( 6 level=logging.debug, # 设置级别,大于等于当前级别的打印出来 7 filename='logger.log', # 指定存放位置,默认为追加的模式 8 filemode='w', # 设置日志的格式 9 format='%(asctime)s %(filename)s [%(lineno)d] %(message)s' 10 11 # %(asctime)s;2019-02-04 19:02:34,392 12 13 # %(asctime)s %(lineno)d 14 # 2019-02-04 19:03:03,556 15 15 # 2019-02-04 19:03:03,556 16 16 # 2019-02-04 19:03:03,556 17 17 # 2019-02-04 19:03:03,556 18 18 # 2019-02-04 19:03:03,557 19 19 20 # %(asctime)s [%(lineno)d] %(message)s 21 # 2019-02-04 19:16:13,040 [20] debug message 22 # 2019-02-04 19:16:13,040 [21] info message 23 # 2019-02-04 19:16:13,040 [22] warning message 24 # 2019-02-04 19:16:13,040 [23] error message 25 # 2019-02-04 19:16:13,040 [24] critical message 26 27 # %(asctime)s %(filename)s [%(lineno)d] %(message)s 28 # 2019-02-04 19:21:47,164 sys_logging.py [26] debug message 29 # 2019-02-04 19:21:47,165 sys_logging.py [27] info message 30 # 2019-02-04 19:21:47,165 sys_logging.py [28] warning message 31 # 2019-02-04 19:21:47,165 sys_logging.py [29] error message 32 # 2019-02-04 19:21:47,165 sys_logging.py [30] critical message 33 ) 34 35 logging.debug('debug message') 36 logging.info('info message') 37 logging.warning('warning message') # warning:root:warning message 38 logging.error('error message') # error:root:error message 39 logging.critical('critical message') # critical:root:critical message
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为‘a’还可指定为‘w’
format:指定handler使用的日志显示格式
datefmt:指定日期时间格式
level:设置rootlogger的日志级别
stream:用指定的stream创建streamhandler。可以指定输出到sys.stderr/sys.stdout或者文件(f=open('test.log', 'w')),默认为sys.stderr,若同时列出了filename和stream两个参数,则stream参数会被忽略。
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:字符串形式的当前时间,默认格式是'2019-02-04 20:07:00,896'。逗号后面的是毫秒
%(thread)d:线程id。可能没有
%(threadname)s:线程名。可能没有
%(process)d:进程id。可能没有
%(message)s:用户输出的消息
三 logger对象
上述几个例子中我们了解了logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical()(分别用以记录不同级别的日志信息),logging.basicconfig()(用默认日志格式(formatter))为日志系统建立一个默认的流处理器(streamhandler),设置基础配置(如日志级别等)并加到(root logger(根logger)中)这几个logging模块级别的函数,另外还有一个模块级别的函数是logging.getlogger([name])(返回一个logger对象,如果没有指定名字将返回root logger)
下面是一个最简单的过程:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import logging 4 logger = logging.getlogger() # 创建一个文件 5 6 fh = logging.filehandler('test_log') 7 ch = logging.streamhandler() 8 9 fm = logging.formatter('%(asctime)s %(message)s') 10 fh.setformatter(fm) 11 ch.setformatter(fm) 12 13 logger.addhandler(fh) 14 logger.addhandler(ch) 15 logger.setlevel('debug') 16 17 logger.debug('debug') 18 logger.info('info') 19 logger.warning('warning') # 2019-02-04 20:38:33,423 warning 20 logger.error('error') # 2019-02-04 20:38:33,423 error 21 logger.critical('critical') # 2019-02-04 20:38:33,424 critical
上一篇: MySQL数据库优化方法