8th,常用模块正则表达式
Posted hellojack
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了8th,常用模块正则表达式相关的知识,希望对你有一定的参考价值。
re模块
什么是正则?
正则就是用一些具有特殊含义的符号组合到一起(正则表达式)来描述字符或者字符串的方法。或者说:正则就是用来描述一类事物的规则。内嵌在Python中,通过re模块实现。正则表达式模式被编译成一系列的字节码,然后由用c编写的匹配引擎执行。
常用正则表达式符号
‘.‘ 默认匹配除\\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行 ‘^‘ 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\\nabc\\neee",flags=re.MULTILINE) ‘$‘ 匹配字符结尾,或e.search("foo$","bfoo\\nsdfsf",flags=re.MULTILINE).group()也可以 ‘*‘ 匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac") 结果为[‘abb‘, ‘ab‘, ‘a‘] ‘+‘ 匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果[‘ab‘, ‘abb‘] ‘?‘ 匹配前一个字符1次或0次 ‘{m}‘ 匹配前一个字符m次 ‘{n,m}‘ 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果‘abb‘, ‘ab‘, ‘abb‘] ‘|‘ 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果‘ABC‘ ‘(...)‘ 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c ‘\\A‘ 只从字符开头匹配,re.search("\\Aabc","alexabc") 是匹配不到的 ‘\\Z‘ 匹配字符结尾,同$ ‘\\d‘ 匹配数字0-9 ‘\\D‘ 匹配非数字 ‘\\w‘ 匹配[A-Za-z0-9] ‘\\W‘ 匹配非[A-Za-z0-9] ‘s‘ 匹配空白字符、\\t、\\n、\\r , re.search("\\s+","ab\\tc1\\n3").group() 结果 ‘\\t‘ ‘(?P<name>...)‘ 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 结果{‘province‘: ‘3714‘, ‘city‘: ‘81‘, ‘birthday‘: ‘1993‘}
最常用的匹配语法
1 re.match 从头开始匹配 2 re.search 匹配包含,会扫描整个字符串,不会从头开始,找到第一个匹配的结果就会返回 3 re.findall 把所有匹配到的字符放到以列表中的元素返回 4 re.splitall 以匹配到的字符当做列表分隔符 5 re.sub 匹配字符并替换
反斜杠
Python原生字符创可以解决反斜杠问题,匹配一个数字可以协亨r"\\d","\\"可以使用r"\\\\"来表示
了解知道的几个匹配模式
re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同) M(MULTILINE): 多行模式,改变‘^‘和‘$‘的行为(参见上图) S(DOTALL): 点任意匹配模式,改变‘.‘的行为
time与datatime模块
在Python中,表示时间的方式:
- 时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。
- 格式化的时间字符串(Format String)
- 结构化的时间(struct_time):struct_time元组共有9个元素(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)
1 import time 2 3 #时间戳 4 print(time.time()) 5 6 #格式化的时间字符串 7 print(time.strftime("%Y-%m-%d %X")) 8 9 #本地时区的struct_time 10 print(time.localtime()) 11 12 #UTC时区的struc_time 13 print(time.gmtime())
其中计算机认识的时间只能是“时间戳”格式,三者之间的转换:
1 #--------------------------按图1转换时间 2 # localtime([secs]) 3 # 将一个时间戳转换为当前时区的struct_time。secs参数未提供,则以当前时间为准。 4 time.localtime() 5 time.localtime(1473525444.037215) 6 7 # gmtime([secs]) 和localtime()方法类似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。 8 9 # mktime(t) : 将一个struct_time转化为时间戳。 10 print(time.mktime(time.localtime()))#1473525749.0 11 12 13 # strftime(format[, t]) : 把一个代表时间的元组或者struct_time(如由time.localtime()和 14 # time.gmtime()返回)转化为格式化的时间字符串。如果t未指定,将传入time.localtime()。如果元组中任何一个 15 # 元素越界,ValueError的错误将会被抛出。 16 print(time.strftime("%Y-%m-%d %X", time.localtime()))#2016-09-11 00:49:56 17 18 # time.strptime(string[, format]) 19 # 把一个格式化时间字符串转化为struct_time。实际上它和strftime()是逆操作。 20 print(time.strptime(‘2011-05-05 16:37:06‘, ‘%Y-%m-%d %X‘)) 21 #time.struct_time(tm_year=2011, tm_mon=5, tm_mday=5, tm_hour=16, tm_min=37, tm_sec=6, 22 # tm_wday=3, tm_yday=125, tm_isdst=-1) 23 #在这个函数中,format默认为:"%a %b %d %H:%M:%S %Y"。
#线程推迟指定的时间运行,单位为秒
sleep(secs)
#时间加减 import datetime # print(datetime.datetime.now()) #返回 2016-08-19 12:47:03.941925 #print(datetime.date.fromtimestamp(time.time()) ) # 时间戳直接转成日期格式 2016-08-19 # print(datetime.datetime.now() ) # print(datetime.datetime.now() + datetime.timedelta(3)) #当前时间+3天 # print(datetime.datetime.now() + datetime.timedelta(-3)) #当前时间-3天 # print(datetime.datetime.now() + datetime.timedelta(hours=3)) #当前时间+3小时 # print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #当前时间+30分 # # c_time = datetime.datetime.now() # print(c_time.replace(minute=3,hour=2)) #时间替换 datetime模块
random模块
import random print(random.random())#(0,1)----float 大于0且小于1之间的小数 print(random.randint(1,3)) #[1,3] 大于等于1且小于等于3之间的整数 print(random.randrange(1,3)) #[1,3) 大于等于1且小于3之间的整数 print(random.choice([1,‘23‘,[4,5]]))#1或者23或者[4,5] print(random.sample([1,‘23‘,[4,5]],2))#列表元素任意2个组合 print(random.uniform(1,3))#大于1小于3的小数,如1.927109612082716 item=[1,3,5,7,9] random.shuffle(item) #打乱item的顺序,相当于"洗牌" print(item)
import random def make_code(n): res=‘‘ for i in range(n): s1=chr(random.randint(65,90)) s2=str(random.randint(0,9)) res+=random.choice([s1,s2]) return res print(make_code(9)) 生成随机验证码
os模块
os模块是与操作系统交互的一个接口
1 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 2 os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd 3 os.curdir 返回当前目录: (‘.‘) 4 os.pardir 获取当前目录的父目录字符串名:(‘..‘) 5 os.makedirs(‘dirname1/dirname2‘) 可生成多层递归目录 6 os.removedirs(‘dirname1‘) 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 7 os.mkdir(‘dirname‘) 生成单级目录;相当于shell中mkdir dirname 8 os.rmdir(‘dirname‘) 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname 9 os.listdir(‘dirname‘) 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 10 os.remove() 删除一个文件 11 os.rename("oldname","newname") 重命名文件/目录 12 os.stat(‘path/filename‘) 获取文件/目录信息 13 os.sep 输出操作系统特定的路径分隔符,win下为"\\\\",Linux下为"/" 14 os.linesep 输出当前平台使用的行终止符,win下为"\\t\\n",Linux下为"\\n" 15 os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为: 16 os.name 输出字符串指示当前使用平台。win->‘nt‘; Linux->‘posix‘ 17 os.system("bash command") 运行shell命令,直接显示 18 os.environ 获取系统环境变量 19 os.path.abspath(path) 返回path规范化的绝对路径 20 os.path.split(path) 将path分割成目录和文件名二元组返回 21 os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素 22 os.path.basename(path) 返回path最后的文件名。如何path以/或\\结尾,那么就会返回空值。即os.path.split(path)的第二个元素 23 os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False 24 os.path.isabs(path) 如果path是绝对路径,返回True 25 os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False 26 os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False 27 os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 28 os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间 29 os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间 30 os.path.getsize(path) 返回path的大小
sys模块
1 sys.argv 命令行参数List,第一个元素是程序本身路径 2 sys.exit(n) 退出程序,正常退出时exit(0) 3 sys.version 获取Python解释程序的版本信息 4 sys.maxint 最大的Int值 5 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 6 sys.platform 返回操作系统平台名称
shutil模块
高级的文件、文件夹、压缩包处理模块
json&pickle模块
eval的重点通常是用来执行一个字符串表达式,并表达式的值。遇到特殊类型时,需要用json。
import json x = "[null, true, false, 1]" print(eval(x)) print(json.loads(x))
什么是序列化?
我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被成为serialization,marshalling, flattening等等,都是一个意思
为什么要序列化?
1、持久保存状态
在断电或重启程序之前将程序当前内存中所有的数据都保存下来(保存到文件中),以便于下次程序执行能够从文件中载入之前的数据,然后继续执行,这就是序列化。
举个栗子:游戏保存并继续;虚拟机状态挂起等
2、跨平台数据交互
序列化之后,不仅可以把序列化后的内容写入磁盘,还可以通过网络传输到别的机器上,如果收发双方约定好使用同一种序列化格式,那么便打破了平台/语言差异化带来的限制,实现了跨平台数据交互。
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
如何序列化:
json
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
JSON表示的对象就是标准的javascript语言的对象,JSON和Python内置的数据类型对应如下:
1 import json 2 3 dic = {"name":"alvin", "age":23, "sex":"male"} 4 print(type(dic)) 5 6 j = json.dumps(dic) 7 print(type(j)) 8 9 f = open("序列化对象", "w") 10 f.write(j)#——————————等价于json.dump(dic, f) 11 f.close() 12 #———————————————反序列化<br> 13 import json 14 f = open("序列化对象") 15 data = json.loads(f.read())
无论数据是怎样创建的,只要满足json格式,就可以json。loads出来,不一定非要dumps的数据才能loads.
pickle
1 import pickle 2 3 dic={‘name‘:‘alvin‘,‘age‘:23,‘sex‘:‘male‘} 4 5 print(type(dic))#<class ‘dict‘> 6 7 j=pickle.dumps(dic) 8 print(type(j))#<class ‘bytes‘> 9 10 11 f=open(‘序列化对象_pickle‘,‘wb‘)#注意是w是写入str,wb是写入bytes,j是‘bytes‘ 12 f.write(j) #-------------------等价于pickle.dump(dic,f) 13 14 f.close() 15 #-------------------------反序列化 16 import pickle 17 f=open(‘序列化对象_pickle‘,‘rb‘) 18 19 data=pickle.loads(f.read())# 等价于data=pickle.load(f) 20 21 22 print(data[‘age‘])
pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于python,并且可能不同版本的Python彼此都不兼容,因此,只能用pickle保存那些不重要的数据,不能成功地反序列化也没关系。
shelve模块
shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以使python所支持的数据类型
1 import shelve 2 3 f=shelve.open(r‘sheve.txt‘) 4 # f[‘stu1_info‘]={‘name‘:‘egon‘,‘age‘:18,‘hobby‘:[‘piao‘,‘smoking‘,‘drinking‘]} 5 # f[‘stu2_info‘]={‘name‘:‘gangdan‘,‘age‘:53} 6 # f[‘school_info‘]={‘website‘:‘http://www.pypy.org‘,‘city‘:‘beijing‘} 7 8 print(f[‘stu1_info‘][‘hobby‘]) 9 f.close()
xml模块xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多。
xml的格式如下,就是通过<>节点来区别数据结构的:
1 <?xml version="1.0"?> 2 <data> 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 <country name="Singapore"> 11 <rank updated="yes">5</rank> 12 <year>2011</year> 13 <gdppc>59900</gdppc> 14 <neighbor name="Malaysia" direction="N"/> 15 </country> 16 <country name="Panama"> 17 <rank updated="yes">69</rank> 18 <year>2011</year> 19 <gdppc>13600</gdppc> 20 <neighbor name="Costa Rica" direction="W"/> 21 <neighbor name="Colombia" direction="E"/> 22 </country> 23 </data> 24 25 xml数据
xml协议在各个语言里都支持,在Python中可以用以下模块操作xml:
1 #print(root.iter("year")) #全文搜索 2 #print(root.find("country"))#在root的子节点找,只找一个 3 #print(root.findall("country"))#在root的子节点找,找所有
1 import xml.etree.ElementTree as ET 2 3 tree = ET.parse("xmltest.xml") 4 root = tree.getroot() 5 print(root.tag) 6 7 #遍历xml文档 8 for child in root: 9 print(‘========>‘,child.tag,child.attrib,child.attrib[‘name‘]) 10 for i in child: 11 print(i.tag,i.attrib,i.text) 12 13 #只遍历year 节点 14 for node in root.iter(‘year‘): 15 print(node.tag,node.text) 16 #--------------------------------------- 17 18 import xml.etree.ElementTree as ET 19 20 tree = ET.parse("xmltest.xml") 21 root = tree.getroot() 22 23 #修改 24 for node in root.iter(‘year‘): 25 new_year=int(node.text)+1 26 node.text=str(new_year) 27 node.set(‘updated‘,‘yes‘) 28 node.set(‘version‘,‘1.0‘) 29 tree.write(‘test.xml‘) 30 31 32 #删除node 33 for country in root.findall(‘country‘): 34 rank = int(country.find(‘rank‘).text) 35 if rank > 50: 36 root.remove(country) 37 38 tree.write(‘output.xml‘)
1 #在country内添加(append)节点year2 2 import xml.etree.ElementTree as ET 3 tree = ET.parse("a.xml") 4 root=tree.getroot() 5 for country in root.findall(‘country‘): 6 for year in country.findall(‘year‘): 7 if int(year.text) > 2000: 8 year2=ET.Element(‘year2‘) 9 year2.text=‘新年‘ 10 year2.attrib={‘update‘:‘yes‘} 11 country.append(year2) #往country节点下添加子节点 12 13 tree.write(‘a.xml.swap‘)
自己创建xml文档:
1 import xml.etree.ElementTree as ET 2 3 4 new_xml = ET.Element("namelist") 5 name = ET.SubElement(new_xml,"name",attrib={"enrolled":"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("test.xml", encoding="utf-8",xml_declaration=True) 15 16 ET.dump(new_xml) #打印生成的格式
configparser模块
用于生成和修改常见配置文档
配置文件如下:
# 注释1 ; 注释2 [section1] k1 = v1 k2:v2 user=egon age=18 is_admin=true salary=31 [section2] k1 = v1
读取
1 import configparser 2 3 config=configparser.ConfigParser() 4 config.read(‘a.cfg‘) 5 6 #查看所有的标题 7 res=config.sections() #[‘section1‘, ‘section2‘] 8 print(res) 9 10 #查看标题section1下所有key=value的key 11 options=config.options(‘section1‘) 12 print(options) #[‘k1‘, ‘k2‘, ‘user‘, ‘age‘, ‘is_admin‘, ‘salary‘] 13 14 #查看标题section1下所有key=value的(key,value)格式 15 item_list=config.items(‘section1‘) 16 print(item_list) #[(‘k1‘, ‘v1‘), (‘k2‘, ‘v2‘), (‘user‘, ‘egon‘), (‘age‘, ‘18‘), (‘is_admin‘, ‘true‘), (‘salary‘, ‘31‘)] 17 18 #查看标题section1下user的值=>字符串格式 19 val=config.get(‘section1‘,‘user‘) 20 print(val) #egon 21 22 #查看标题section1下age的值=>整数格式 23 val1=config.getint(‘section1‘,‘age‘) 24 print(val1) #18 25 26 #查看标题section1下is_admin的值=>布尔值格式 27 val2=config.getboolean(‘section1‘,‘is_admin‘) 28 print(val2) #True 29 30 #查看标题section1下salary的值=>浮点型格式 31 val3=config.getfloat(‘section1‘,‘salary‘) 32 print(val3) #31.0
改写
1 import configparser 2 3 config=configparser.ConfigParser() 4 config.read(‘a.cfg‘,encoding=‘utf-8‘) 5 6 7 #删除整个标题section2 8 config.remove_section(‘section2‘) 9 10 #删除标题section1下的某个k1和k2 11 config.remove_option(‘section1‘,‘k1‘) 12 config.remove_option(‘section1‘,‘k2‘) 13 14 #判断是否存在某个标题 15 print(config.has_section(‘section1‘)) 16 17 #判断标题section1下是否有user 18 print(config.has_option(‘section1‘,‘‘)) 19 20 21 #添加一个标题 22 config.add_section(‘egon‘) 23 24 #在标题egon下添加name=egon,age=18的配置 25 config.set(‘egon‘,‘name‘,‘egon‘) 26 config.set(‘egon‘,‘age‘,18) #报错,必须是字符串 27 28 29 #最后将修改的内容写入文件,完成最终的修改 30 config.write(open(‘a.cfg‘,‘w‘))
基于上述方法添加一个ini文档
1 import configparser 2 3 config = configparser.ConfigParser() 4 config["DEFAULT"] = {‘ServerAliveInterval‘: ‘45‘, 5 ‘Compression‘: ‘yes‘, 6 ‘CompressionLevel‘: ‘9‘} 7 8 config[‘bitbucket.org‘] = {} 9 config[‘bitbucket.org‘][‘User‘] = ‘hg‘ 10 config[‘topsecret.server.com‘] = {} 11 topsecret = config[‘topsecret.server.com‘] 12 topsecret[‘Host Port‘] = ‘50022‘ # mutates the parser 13 topsecret[‘ForwardX11‘] = ‘no‘ # same here 14 config[‘DEFAULT‘][‘ForwardX11‘] = ‘yes‘ 15 with open(‘example.ini‘, ‘w‘) as configfile: 16 config.write(configfile) 17 18 #基于上述方法添加一个ini文档
hashlib模块
什么是hash?
hash是一种算法(3.x里代替了md5模块和sha模块,主要提供SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法),该算法接受传入的内容,经过运算得到一串hash值
hash值的特点
(1)只要传入的内容一样,得到的hash值必然一样===》要用明文传输密码文件完整性校验
(2)不能由hash值反解成内容===》把密码做成hash值,不应该在网络传输明文密码
(3)只要使用的hash算法不便,无论校验的内容有多大,得到的hash值长度是固定的
hash算法就像一座工厂,工厂接收你送来的原材料(可以用m.update()为工厂运行原材料),经过加工返回的产品就是hash值
1 import hashlib 2 3 m=hashlib.md5()# m=hashlib.sha256() 4 5 m.update(‘hello‘.encode(‘utf8‘)) 6 print(m.hexdigest()) #5d41402abc4b2a76b9719d911017c592 7 8 m.update(‘alvin‘.encode(‘utf8‘)) 9 10 print(m.hexdigest()) #92a7e713c30abbb0319fa07da2a5c4af 11 12 m2=hashlib.md5() 13 m2.update(‘helloalvin‘.encode(‘utf8‘)) 14 print(m2.hexdigest()) #92a7e713c30abbb0319fa07da2a5c4af 15 16 ‘‘‘ 17 注意:把一段很长的数据update多次,与一次update这段长数据,得到的结果一样 18 但是update多次为校验大文件提供了可能。 19 ‘‘‘
以上加密算法虽然非常厉害,但有时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密
1 import hashlib 2 3 #####256##### 4 5 hash = hashlib.sha256("898oaFs09f".encode("utf8")) 6 hahs.update("alvin".encode("utf8")) 7 print(hash.hexdigest())
python还有一个hmac模块,它内部对我们创建key和内容进行进一步的处理然后再加密:
1 import hmac 2 h = hmac.new("alvin".encode("utf8")) 3 h.update("hello".encode("utf8")) 4 print(h.hexdigest())
1 #要想保证hmac最终结果一致,必须保证: 2 #1:hmac.new括号内指定的初始key一样 3 #2:无论update多少次,校验的内容累加到一起是一样的内容 4 5 import hmac 6 7 h1=hmac.new(b‘egon‘) 8 h1.update(b‘hello‘) 9 h1.update(b‘world‘) 10 print(h1.hexdigest()) 11 12 h2=hmac.new(b‘egon‘) 13 h2.update(b‘helloworld‘) 14 print(h2.hexdigest()) 15 16 h3=hmac.new(b‘egonhelloworld‘) 17 print(h3.hexdigest()) 18 19 ‘‘‘ 20 f1bf38d054691688f89dcd34ac3c27f2 21 f1bf38d054691688f89dcd34ac3c27f2 22 bcca84edd9eeb86f30539922b28f3981 23 ‘‘‘ 24 25 #注意!注意!注意
subprocess模块
subprocess模块允许用户建立新程序,连接至其输入、输出、错误句柄并得到他们的返回代码
subprocess.run() #可以用于所有可以处理的情况;
‘‘‘
subprocess.
run
(args, *, stdin=None, input=None, stdout=None, stderr=None,
shell=False, timeout=None, check=False)
‘‘‘
subprocess.Popen() #可以用于更高级的用途
常用subprocess方法
1 #执行命令,返回命令执行状态 , 0 or 非0 2 >>> retcode = subprocess.call(["ls", "-l"]) 3 4 #执行命令,如果命令结果为0,就正常返回,否则抛异常 5 >>> subprocess.check_call(["ls", "-l"]) 6 0 7 8 #接收字符串格式命令,返回元组形式,第1个元素是执行状态,第2个是命令结果 9 >>> subprocess.getstatusoutput(‘ls /bin/ls‘) 10 (0, ‘/bin/ls‘) 11 12 #接收字符串格式命令,并返回结果 13 >>> subprocess.getoutput(‘ls /bin/ls‘) 14 ‘/bin/ls‘ 15 16 #执行命令,并返回结果,注意是返回结果,不是打印,下例结果返回给res 17 >>> res=subprocess.check_output([‘ls‘,‘-l‘]) 18 >>> res 19 b‘total 0\\ndrwxr-xr-x 12 alex staff 408 Nov 2 11:05 OldBoyCRM\\n‘ 20 21 #上面那些方法,底层都是封装的subprocess.Popen 22 poll() 23 Check if child process has terminated. Returns returncode 24 25 wait() 26 Wait for child process to terminate. Returns returncode attribute. 27 28 29 terminate() 杀掉所启动进程 30 communicate() 等待任务结束 31 32 stdin 标准输入 33 34 stdout 标准输出 35 36 stderr 标准错误 37 38 pid 39 The process ID of the child process. 40 41 #例子 42 >>> p = subprocess.Popen("df -h|grep disk",stdin=subprocess.PIPE,stdout=subprocess.PIPE,shell=True) 43 >>> p.stdout.read() 44 b‘/dev/disk1 465Gi 64Gi 400Gi 14% 16901472 104938142 14% /\\n‘
终端输入的命令分为两种:
(1)输入即可得到输出,如:ifconfig
(2)输入进行某环境,依赖再输入,如:python
需要交互的命令示例
1 import subprocess 2 3 obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 4 obj.stdin.write(‘print 1 \\n ‘) 5 obj.stdin.write(‘print 2 \\n ‘) 6 obj.stdin.write(‘print 3 \\n ‘) 7 obj.stdin.write(‘print 4 \\n ‘) 8 9 out_error_list = obj.communicate(timeout=10) 10 print out_error_list
1 import subprocess 2 3 ‘‘‘ 4 sh-3.2# ls /Users/egon/Desktop |grep txt$ 5 mysql.txt 6 tt.txt 7 事物.txt 8 ‘‘‘ 9 10 res1=subprocess.Popen(‘ls /Users/jieli/Desktop‘,shell=True,stdout=subprocess.PIPE) 11 res=subprocess.Popen(‘grep txt$‘,shell=True,stdin=res1.stdout, 12 stdout=subprocess.PIPE) 13 14 print(res.stdout.read().decode(‘utf-8‘)) 15 16 17 #等同于上面,但是上面的优势在于,一个数据流可以和另外一个数据流交互,可以通过爬虫得到结果然后交给grep 18 res1=subprocess.Popen(‘ls /Users/jieli/Desktop |grep txt$‘,shell=True,stdout=subprocess.PIPE) 19 print(res1.stdout.read().decode(‘utf-8‘)) 20 21 22 #windows下: 23 # dir | findstr ‘test*‘ 24 # dir | findstr ‘txt$‘ 25 import subprocess 26 res1=subprocess.Popen(r‘dir C:\\Users\\Administrator\\PycharmProjects\\test\\函数备课‘,shell=True,stdout=subprocess.PIPE) 27 res=subprocess.Popen(‘findstr test*‘,shell=True,stdin=res1.stdout, 28 stdout=subprocess.PIPE) 29 30 print(res.stdout.read().decode(‘gbk‘)) #subprocess使用当前系统默认编码,得到结果为bytes类型,在windows下需要用gbk解码
logging模块
很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还有可能有错误、警告等信息输出,python的loggin模块提供了标准的日志接口,可以通过它存储各种格式的日志,logging的日志可以分为debug(), info(), warning(), error() 和critical()5个级别。
1 #最简单用法 2 import logging 3 4 logging.warning("user [alex] attempted wrong password more than 3 times") 5 logging.critical("server is down") 6 7 #输出 8 WARNING:root:user [alex] attempted wrong password more than 3 times 9 CRITICAL:root:server is down
各个级别的含义:
level | 信息 |
debug | 详细信息,通常只在诊断问题的时候使用 |
info | 程序正如期望的工作的确认信息 |
warning | 某些不期望发生的事情的指示,或者未来一些问题的指示。软件仍然在期望的状态下运行 |
error | 由于更严重的问题,软件已经不能表现一些功能 |
critical | 严重的错误,表明程序已经不能继续运行 |
把日志写到文件里
1 import logging 2 3 logging.basicConfig(filename=‘example.log‘,level=logging.INFO) 4 logging.debug(‘This message should go to the log file‘) 5 logging.info(‘So should this‘) 6 logging.warning(‘And this, too‘)
其中level=loggin.INFO意思是,把日志记录级别设置为INFO,也就是说,只有比日志是INFO或比INFO级别更高的日志才会被记录到文件里,上面代码中,第一条日志是不会被记录的,如果希望记录debug日志,需要把日志级别改为DEBUG。
在日志中加上时间
1 import logging 2 logging.basicConfig(format=‘%(asctime)s %(message)s‘, datefmt=‘%m/%d/%Y %I:%M:%S %p‘) 3 logging.warning(‘is when this event was logged.‘) 4 5 #输出 6 12/12/2010 11:46:36 AM is when this event was logged.
%(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 |
用户输出的消息 |
以上是关于8th,常用模块正则表达式的主要内容,如果未能解决你的问题,请参考以下文章