PYTHON开发必备技能(3)
第四名:正则表达式re模块
参考网址:http://www.runoob.com/python3/python3-reg-expressions.html
Group(1,2)
正则表达式是一个很强大的字符串处理工具,几乎任何关于字符串的操作都可以使用正则表达式来完成。
注意:正则表达式处理的数据单位为单个字符。
Python正则表达式当中元字符的各种用法:
\w:匹配字母数字以及下划线,相当于[a-zA-Z0-9_] \W: 匹配非字母数字以及下划线,相当于[^a-zA-Z0-9_] \d: 匹配数字0-9,相当于[0-9] \D: 匹配非数字0-9,相当于[^0-9] \s: 匹配任意空白字符,相当于[\t\n\r\f\v] \S: 匹配任意非空白字符,相当于[^\t\n\r\f\v] 对于上面的这些预定义字符集,可以放在字符集[...]当中。 . : 默认匹配除\n之外的任意单个字符,若指定flags=re.DOTALL,则匹配任意字符,包括换行 * :匹配*号前面的字符0次或者多次 + :匹配+号前面的字符一次或者多次 ?:匹配?号前面的字符一次或者0次 ^: 代表已某个字符开头,多行模式下匹配每一行的开始 $: 代表已某个字符结尾,多行模式下匹配每一行的结尾 |:匹配|左边或者右边的字符 []:字符集,字符的集合,可匹配其中任意一个字符,^在字符集[]里面代表取反的意思,对于预定义字符集,可以放在[...]当中 {m,n}:匹配前一个字符m到n次,若省略n,代表匹配前面的字符m次到无穷次,通过{}可以模拟? + * 的功能 \:转义字符,跟在其后的字符将失去作为特殊元字符的含义,例如\.只能匹配.,不能再匹配任意字符
示例程序:.在默认情况下是不匹配换行符的,请写出匹配\n的程序
#!/usr/bin/python # -*- encoding:utf-8 -*- import re s = '''first 111 line second 222 line third 333 line''' print(re.findall('.+',s,flags=0)) print(re.findall('.+',s,flags=re.S))
运行结果:
['first 111 line', 'second 222 line', 'third 333 line'] ['first 111 line\nsecond 222 line\nthird 333 line']
示例程序:请列举出一个例子,说明转义字符\的用法
#!/usr/bin/python # -*- encoding:utf-8 -*- import re s='the sum of 7 and 9 is [7+9].' print(re.search('\[\d\+\d+\]',s)) print(re.search('\[\d\+\d+\]',s).group())
运行结果:
<_sre.SRE_Match object at 0x7efdbb5fc370> [7+9]
Python正则表达式常用的三剑客函数:
正则表达式当中re.findall、re.search、re.match的用法:
Python的re模块提供了很多方便的函数使你可以使用正则表达式来操作字符串:
re.findall:遍历匹配,可以获取字符串中所有匹配的字符串,返回一个列表
re.search :遍历匹配,仅可以获取到字符串当中第一个满足匹配条件的字符串然后返回,如果没有匹配到字符串,则返回None
(函数类似于 match,不同之处在于不限制正则表达式的开始匹配位置)
re.match : 从字符串的开头进行匹配,不进行遍历匹配。
示例程序:
#!/usr/bin/python # -*- encoding:utf-8 -*- import re #获取到所有匹配到的字符串 print(re.findall('\woo\w','hol tool good wallool')) #进获取到第一个满足条件的字符串 print(re.search('\woo\w','hol tool good wallool')) print(re.search('\woo\w','hol tool good wallool').group()) #从头开始匹配,并获取一个 print(re.match('\woo\w','hol tool good wallool'))
运行结果:
['tool', 'good', 'lool'] <_sre.SRE_Match object; span=(4, 8), match='tool'> tool None
Python正则表达式分组的相关用法:
正则表达式当中()分组的概念:
所谓分组,就是在匹配成功的字符串当中,在提取()里组里面的字符串。
简述无名分组和有名分组:
无名分组通过findall、search、match都可以实现,有名分组只能通过search、match实现。
简述group的用法:(只有search和match含有该方法)
在正则表达式当中,对于返回类型为表达式对象的,需要用正则方法获取相应的字符串。
group() 不管有没有分组将匹配到的结果全部拿出来,等价于group(0) ===>字符串
groups() 只拿出分组部分的结果 ===>元组
groupdict() 只拿出分组部分定义了key的结果 ====>字典
注意:通过group()可以实现groups()和groupdict()的结果。
示例程序:分组的相关用法(请获取用户名和出生日期)
#!/usr/bin/python # -*- encoding:utf-8 -*- import re s = 'Hello, Mr.Gumby : 2016/10/26' print(re.findall('\w+,\s\w+.\w+\s:\s.+',s,flags=0)) print(re.findall('\w+,\s(\w+.\w+)\s:\s(.+)',s,flags=0)) #全部输出 print(re.search('\w+,\s(\w+.\w+)\s:\s(.+)',s,flags=0).group()) #只输出分组的 print(re.search('\w+,\s(\w+.\w+)\s:\s(.+)',s,flags=0).groups()) #只输出分组带key的 print(re.search('\w+,\s(\w+.\w+)\s:\s(?P<birthday>.+)',s,flags=0).groupdict())
运行结果:
['Hello, Mr.Gumby : 2016/10/26'] [('Mr.Gumby', '2016/10/26')] Hello, Mr.Gumby : 2016/10/26 ('Mr.Gumby', '2016/10/26') {'birthday': '2016/10/26'}
运行结果:
Hello, Mr.Gumby : 2016 Hello, Mr.Gumby : 2016 Mr.Gumby 2016 Mr.Gumby 2016 Traceback (most recent call last): File "aa.py", line 21, in <module> print(re.findall('\w+,\s(\w+\.\w+)\s:\s(\w+)',s,flags=re.S).group()) AttributeError: 'list' object has no attribute 'group'
贪婪匹配和非贪婪匹配的概念:
对于?* + {m,n}这些元字符,默认都是贪婪匹配,即尽可能向后面多的匹配字符。如果这些元字符的后面加上?号将变为非贪婪匹配。
正则表达式当中?的概念:
通过?:可以将()分组的功能进行侵蚀
通过?可以将? * + {m,n}这些元字符的贪婪匹配模式转化为非贪婪匹配模式
示例程序:贪婪模式和非贪婪模式
#!/usr/bin/python # -*- encoding:utf-8 -*- import re print(re.findall('a.*b','a1b22222222b')) print(re.findall('a.+b','a1b22222222b')) print(re.findall('a.*?b','a1b22222222b')) print(re.findall('a.+?b','a1b22222222b'))
运行结果:
['a1b22222222b'] ['a1b22222222b'] ['a1b'] ['a1b']
Python正则表达式当中re.compile()的用法:
正则表达式当中re.compile()的用法:
re.compile():将正则表达式编译成正则表达式对象
示例程序:
#!/usr/bin/python # -*- encoding:utf-8 -*- import re pattern = re.compile('\w+') str_info = 'hello egon 123' print(pattern.findall(str_info)) print(re.split('egon',str_info))
str_info = "the sum of 7 and 9 is [7+9]." print(re.sub('\[\d\+\d\]','16',str_info))
运行结果:
['hello', 'egon', '123'] ['hello ', ' 123'] the sum of 7 and 9 is 16.
第5名:操作系统os模块与sys模块
os模块,语义为操作系统,os模块是与操作系统交互的一个接口。通过os模块可以处理文件和目录这些我们日常需要手动处理的操
作,比如:显示当前目录下的所有文件、删除某个文件、获取文件的大小等等。
os模块的常用功能如下所示:
=========================================================================== os模块是与操作系统交互的一个接口 os.getcwd():获取当前python脚本的工作目录 os.chdir('dirname'):改变当前脚本的工作目录,相当于shell下的cd命令 os.curdir('返回当前的工作目录,相当于.') os.pardir:获取当前目录的父目录字符串名,相当于.. os.listdir(r'dirname'):列出指定目录下的所有文件和子目录,包括隐藏文件,并已列表的方式打印输出 os.makedirs('dirname1/dirname2'):创建多层递归目录,相当于shell下的make -p,如果创建的文件夹已经存在, 为了防止报错,可以采用参数:exist_ok=True os.removedirs('dirname1'):递归的删除空目录:若目录为空,则删除,并递归到上一层目录,如若也为空,则删除,依次类推 os.mkdir('dirname'):生成单级目录,相当于shell中的mkdir dirname os.rmdir('dirname'):删除单级目录 os.remove():用来删除一个文件,不是用来删除文件夹的 os.rename('oldname','newname'):重命名文件,目录 os.stat('path/filename'):获取文件/目录的相关信息 os.sep:输出操作系统特定的路径分隔符,win下面为'\',linux下面为'/',根据系统的不同,动态的拼接路径 os.linesep:输出当前平台使用的行终止符,win下面为'\r\n',linux下面为'\n' os.name:输出当前所使用的平台.win下面为'nt',linux下面为'posix' os.environ:获取系统的环境变量
os.getenv():获取一个环境变量对应的数值,如果没有返回None
os.system("bash command"):运行shell命令,直接显示===>提倡用subprocess模块
===========================================================================
os模块中和path相关的用法:
判断某一个路径是否存在: os.path.exists(path):如果path存在,返回True;如果path不存在,返回False 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.path.abspath(path):返回path规范化的绝对路径 os.path.split(path):将path分割成目录和文件名二元组返回 os.path.splitext(path):分离文件名与扩展名 os.path.dirname(path):返回path的目录,其实就是os.path.split(path)的第一个元素,并不会判断最后一层是否是文件夹还是文件 os.path.exists(path):如果path存在,将返回True,如果path不存在,将返回False os.path.join():将多个路径组合后返回,第一个绝对路径路径之前的参数将被忽略
第一题:将执行文件所在的父目录的父目录添加到环境变量PATH当中。
方法1:
#!/usr/bin/python # -*- coding:utf-8 -*- import sys import os base_dir = os.path.abspath(os.pardir) print('\033[33m执行文件的父目录的父目录是:%s\033[0m'%base_dir) sys.path.append(base_dir) print('\033[42m模块的搜索路径是:\033[0m') for path in sys.path: print(path)
方法2:
#!/usr/bin/python # -*- coding:utf-8 -*- import sys import os print(os.path.abspath(__file__)) base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) print(base_dir) print('==============>') sys.path.append(base_dir) for path in sys.path: print(path)
第二题:判断执行文件所在的当前目录的下面是否存在日志目录,如果不存在,则进行创建。
#!/usr/bin/python # -*- coding:utf-8 -*- import sys import os base_dir = os.path.abspath(os.curdir) log_dir = os.path.join(base_dir,'log_dir') if os.path.exists(log_dir): print('\033[42m日志目录log_dir存在..\033[0m') else: print('\033[42m日志目录log_dir不存在,进行创建.\033[0m') os.makedirs(log_dir,exist_ok=True)
方法2:
#!/usr/bin/python # -*- coding:utf-8 -*- import sys import os base_dir = os.path.abspath(os.curdir) print(base_dir) log_dir = '%s%slog_dir'%(base_dir,os.sep) print(log_dir) if os.path.exists(log_dir): print('日志目录存在..') else: print('日志目录不存在,进行创建..') os.makedirs(log_dir,exist_ok=True)
第三题:判断当前文件所在的当前目录的下面是否存在当天日志的日志文件,如果存在,则进行删除,如果不存在,则进行创建。
#!/usr/bin/python # -*- coding:utf-8 -*- import sys import os import time base_dir = os.path.abspath(os.curdir) log_time = time.strftime('%Y-%m-%d',time.localtime(time.time())) log_filename = os.path.join(base_dir,'%s.txt'%log_time) if os.path.isfile(log_filename): print('日志文件已经存在,进行删除..') os.remove(log_filename) print('日志文件删除成功..') else: print('日志文件不存在,接下来进行创建..') with open(log_filename,mode='w',encoding='utf-8') as fw: pass
实战代码:
def format_dir(path_dir): if not path_dir.endswith("/"): path_dir+="/" return path_dir def mkdir(path): if not os.path.exists(path): os.makedirs(path) def remove_file(target_file): if os.path.exists(target_file): os.remove(target_file)
sys模块常用的功能:
sys.path:返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的数值 sys.argv:命令行参数List,第一个元素是程序本身的路径 sys.stdout:标准输出,基本不怎么用(用print进行替代) sys.exit(n):退出程序,正常退出时exit(0)===>调度系统
注意:在pycharm中执行无效,请到命令行中已脚本的方式执行(\r代表跳转到当前行首的意思)
命令行代码示例1:
#!/usr/bin/python # -*- coding:utf-8 -*- import sys import os import time for item in sys.argv: print(item) print('===========>') print(sys.argv[0]) print(sys.argv[1])
运行示例:
[root@iz2zea81ksgk8xh72ofrr0z zmy]# python3 os_exe.py python hello os_exe.py python hello ===========> os_exe.py python
示例程序2:倒计时程序
#!/usr/bin/python # -*- coding:utf-8 -*- import sys import os import time for i in range(0,50): print('%s\r'%('*'*i),end='') time.sleep(1)
第6名:解析配置文件的模块configparser模块
Python当中configparser模块的用法:
在Python当中,configparser模块的作用是通过使用在模块当中定义的ConfigParser类,创建一个类对象并通过该对象的方法对指定的配置文件做增删改查操作,配置文件的格式和windows的INI文件的格式相同,配置文件的格式如下:中括号[]内包含的为section,
section下面为类似key-value的配置内容。
[db] db_host = 127.0.0.1 db_port = 22 db_user = root db_pass = rootroot [concurrent] thread = 10 processor = 20
ConfigParser类对象常用的方法:
read(filename) : 直接读取ini配置文件的内容 sections():获取所有sections,即将配置文件中所有“[ ]”读取到列表中 options(section) :获取指定section 的options,即将配置文件某个section 内key 读取到列表中 items(section) : 获取指定section的所有键值对配置信息 get(section,option) : 按照类型读取指定section 的option 信息 set(section, option, value):设置section下面对应option的数值
示例程序1:如何用python生成configparser类似的配置文件呢,代码如下:
from configparser import ConfigParser import os config = ConfigParser() config.read('example.ini',encoding='utf-8') if config.has_section('db'): pass else: config.add_section('db') with open('example.ini',mode='w') as fw: config.write(fw) config['db'] = { 'db_host':'127.0.0.1', 'db_port':'22', 'db_user':'root', 'db_pass':'rootroot', } with open('example.ini',mode='w') as fw: config.write(fw) if config.has_section('concurrent'): pass else: config.add_section('concurrent') config.set('concurrent','thread','10') config.set('concurrent','processor','20') with open('example.ini',mode='w') as fw: config.write(fw)
示例程序2:如何用config读取相应配置文件的信息呢,代码如下(重点)
from configparser import ConfigParser """ 通过configparser模块读取相应的配置文件的内容 """ config = ConfigParser() config.read('example.ini',encoding='utf-8') #sections():获取所有sections,即将配置文件中所有[ ]都读取到列表中 for section in config.sections(): print(section) #获取指定section 的options,即将配置文件中某个section 内key 读取到列表中 for option in config.options('db'): print(option) for option in config.options('concurrent'): print(option) #获取指定section的所有键值对配置信息 for key,value in config.items('db'): print(key,value) for key,value in config.items('concurrent'): print(key,value) #get(section,option) : 按照类型读取指定section 的option 信息 print(config.get('db','db_host'),type(config.get('db','db_host'))) print(config.getint('concurrent','thread'),type(config.getint('concurrent','thread'))) #set(section, option, value):设置与修改section下面对应option的数值 config.set('db','db_host','192.168.80.100') config.set('concurrent','num','200') with open('example.ini',mode='w') as fw: config.write(fw)
示例程序3:configparser模块其余的一些用法
from configparser import ConfigParser config = ConfigParser() config.read('example.ini',encoding='utf-8') #判断配置文件是否具有某个section print(config.has_section('section1')) print(config.has_section('section3')) #判断配置文件的某个section下面是否具有某个option print(config.has_option('section1','k1')) print(config.has_option('section1','k3')) #删除配置文件的某个section if config.has_section('section2'): config.remove_section('section2') with open('example.ini',encoding='utf-8',mode='w') as fw: config.write(fw) else: pass #删除配置文件的某个section下面的option if config.has_option('section1','k1'): config.remove_option('section1','k1') with open('example.ini',encoding='utf-8',mode='w') as fw: config.write(fw) else: pass #判断某一个section是否存在,如果不存在,进行创建 if config.has_section('person_info'): pass else: config.add_section('person_info') with open('example.ini', encoding='utf-8', mode='w') as fw: config.write(fw) #为某一个section下面添加option和value config.set('section1','city','beijing') with open('example.ini', encoding='utf-8', mode='w') as fw: config.write(fw) #重置某一个value config.set('section1','user','angela') with open('example.ini', encoding='utf-8', mode='w') as fw: config.write(fw)
实战项目:
对于下面的数据,请转化成规定的格式:
[jdw] ns1=172.22.168.99,172.22.168.100 ns2=172.22.168.101,172.22.168.102 ns3=172.22.167.71,172.22.167.72 ns4=172.22.167.67,172.22.167.68 ns5=172.22.167.69,172.22.167.70 [jmart] ns1=172.19.167.11,172.19.167.12 ns2=172.19.167.13,172.19.167.14
要求格式:
{'jmart': {'ns2': '172.19.167.13,172.19.167.14', 'ns1': '172.19.167.11,172.19.167.12'}, 'jdw': {'ns3': '172.22.167.71,172.22.167.72', 'ns2': '172.22.168.101,172.22.168.102', 'ns1': '172.22.168.99,172.22.168.100', 'ns4': '172.22.167.67,172.22.167.68', 'ns5': '172.22.167.69,172.22.167.70'}} Process finished with exit code 0
代码示例:
#!/usr/bin/python # -*- coding:utf-8 -*- from configparser import ConfigParser import os,sys config = ConfigParser() config_file = os.path.join(os.path.dirname(os.path.abspath(__file__)),'conf.cfg') config.read(config_file,encoding='utf-8') namenode_info = {} for section in config.sections(): namenode_info[section] = {} for option in config.options(section): namenode_info[section][option] = config[section][option] print(namenode_info)