博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python 基础之-常用模块
阅读量:5260 次
发布时间:2019-06-14

本文共 34885 字,大约阅读时间需要 116 分钟。

一 time & datetime

在Python中,通常有如下几种方式来表示时间:

  • 时间戳(timestamp):  通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行"type(time.time())",返回的是float类型。
  • 格式化的时间字符串(Format String)
  • 结构化的时间(struct_time):  struct_time元祖共有9个元素(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)
>>> import time#-------------------------以下分别是三种形式的时间-----------------------#>>> print(time.time())    #时间戳1509802396.6130548>>> print(time.strftime('%Y-%m-%d %X'))    #格式化的时间字符串,默认按当前时间(time.localtime())进行格式化2017-11-04 21:34:03>>> print (time.strftime('%a %b %d %H:%M:%S %Y'))    #格式化的时间字符串,同上一个Sat Nov 04 21:35:40 2017>>> print(time.localtime())    #本地时区的struct_timetime.struct_time(tm_year=2017, tm_mon=11, tm_mday=4, tm_hour=21, tm_min=34, tm_sec=40, tm_wday=5, tm_yday=308, tm_isdst=0)>>> print(time.gmtime())    #UTC时区的struct_timetime.struct_time(tm_year=2017, tm_mon=11, tm_mday=4, tm_hour=13, tm_min=34, tm_sec=57, tm_wday=5, tm_yday=308, tm_isdst=0)
%y 去掉世纪的年份表示(00 - 99)%Y 完整的年份表示(0000 - 9999)%m 月份(01 - 12)%d 一个月中的第几天(01 - 31)%H 24小时制小时数(00 - 23)%I 12小时制小时数(01 - 12)%M 分钟数(00 - 59)%S 秒(00 - 59)%a 本地(locale)简化星期名称%A 本地完整星期名称%b 本地简化的月份名称%B 本地完整的月份名称%c 本地相应的日期表示和时间表示%j 一年中的第几天(001 - 366)%p 本地A.M.或P.M.的等价符%U 一年中的星期数(00 - 53)星期天为星期的开始%w 一个星期中的第几天(0 - 6),星期天为星期的开始%W 和%U基本相同,不同的是%W是以星期一为一个星期的开始%x 本地相应的日期表示%X 本地相应的时间表示%Z 当前时区的名称(如果不存在为空字符)%% %号本身
格式化字符串的时间格式

 

其中计算机认识的时间只能是'时间戳'格式,而程序员可处理的或者说人类能看懂的时间有: '格式化的时间字符串','结构化的时间' ,于是有了下图的转换关系

          

>>> import time#-------------------------------------按图1转换时间------------------------------------------## localtime([secs]):将一个时间戳转换为当前时区(UTC+8)的struct_time。secs参数未提供,则以当前时间为准。>>> time.localtime()time.struct_time(tm_year=2017, tm_mon=11, tm_mday=4, tm_hour=21, tm_min=57, tm_sec=41, tm_wday=5, tm_yday=308, tm_isdst=0)>>> x = time.localtime(1509802396.6130548)>>> print(x)time.struct_time(tm_year=2017, tm_mon=11, tm_mday=4, tm_hour=21, tm_min=33, tm_sec=16, tm_wday=5, tm_yday=308, tm_isdst=0)>>> print(x.tm_year)2017>>> print(x.tm_yday)308# gmtime([secs]) 和localtime()方法类似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。# mktime(t) : 将一个struct_time转化为时间戳。>>> print(time.mktime(time.localtime()))1509803970.0# strftime(format[, t]) : 把一个代表时间的元组或者struct_time(如由time.localtime()和time.gmtime()返回)转化为格式化的时间字符串。  如果t未指定,将传入time.localtime()。如果元组中任何一个元素越界,ValueError的错误将会被抛出。>>> print(time.strftime("%Y-%m-%d %X", time.localtime()))2017-11-04 22:00:32>>> print(time.strftime("%X %Y-%m-%d", time.localtime()))22:00:32 2017-11-04# time.strptime(string[, format]):把一个格式化时间字符串转化为struct_time。实际上它和strftime()是逆操作。>>> print(time.strptime('2017-11-04 22:00:32', '%Y-%m-%d %X'))time.struct_time(tm_year=2017, tm_mon=11, tm_mday=4, tm_hour=22, tm_min=0, tm_sec=32, tm_wday=5, tm_yday=308, tm_isdst=-1)#在这个函数中,format默认为:"%a %b %d %H:%M:%S %Y"。
>>> import time#将格式字符串转换为时间戳>>> string_to_struct = time.strptime("2017-10-30 14:48:44","%Y-%m-%d %H:%M:%S")     #将 日期字符串 转成 struct时间对象格式>>> print(string_to_struct)time.struct_time(tm_year=2017, tm_mon=10, tm_mday=30, tm_hour=14, tm_min=48, tm_sec=44, tm_wday=0, tm_yday=303, tm_isdst=-1)>>> struct_to_stamp = time.mktime(string_to_struct)     #将struct时间对象格式转成时间戳>>> print(struct_to_stamp)1509346124.0或者一步到位>>> print(time.mktime(time.strptime("2017-10-30 14:48:44","%Y-%m-%d %H:%M:%S")) )1509346124.0#将时间戳转换为格式字符串>>> print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(1509346124.0)) )2017-10-30 14:48:44
格式字符串和时间戳互转

 

            

>>> import time#-----------------------------------------按图2转换时间-------------------------------------------## asctime([t]) : 把一个表示时间的元组或者struct_time表示为这种形式:'Sun Jun 20 23:21:05 1993'。如果没有参数,将会将time.localtime()作为参数传入。>>> print(time.asctime())Sat Nov  4 22:19:37 2017# ctime([secs]) : 把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式。如果参数未给或者为None的时候,将会默认time.time()为参数。 它的作用相当于time.asctime(time.localtime(secs))。>>> print(time.ctime())Sat Nov  4 22:19:56 2017>>> print(time.ctime(time.time()))Sat Nov  4 22:20:35 2017#---------------------------------------其它用法---------------------------## sleep(secs):线程推迟指定的时间运行,单位为秒。
#时间加减>>> import datetime>>> print(datetime.datetime.now())    #返回当前时间2017-11-04 22:28:16.976757>>> print(datetime.date.fromtimestamp(time.time()) )    # 时间戳直接转成日期格式2017-11-04>>> print(datetime.datetime.now() )2017-11-04 22:29:12.067908>>> print(datetime.datetime.now() + datetime.timedelta(3))    #当前时间+3天2017-11-07 22:29:24.544621>>> print(datetime.datetime.now() + datetime.timedelta(-3))   #当前时间-3天 2017-11-01 22:29:38.412414>>> print(datetime.datetime.now() + datetime.timedelta(hours=3))    #当前时间+3小时2017-11-05 01:29:50.667115>>> print(datetime.datetime.now() + datetime.timedelta(minutes=30))    #当前时间+30分2017-11-04 23:00:03.260836>>> c_time  = datetime.datetime.now()>>> print(c_time.replace(minute=3,hour=2))    #时间替换2017-11-04 02:03:37.749808
datetime模块

 

二 random

随机数

>>> import random>>> print(random.random())    #(0,1)----float    大于0且小于1之间的小数。也可以指定区间,看下一个0.4389206383156363>>> print(random.uniform(1,3))    #大于1小于3的小数1.8623602068930234>>> print(random.randint(1,3))    #[1,3]    大于等于1且小于等于3之间的整数1>>> print(random.randrange(1,3))    #[1,3)    大于等于1且小于3之间的整数2>>> print(random.choice([1,'23',[4,5]]))    #1或者23或者[4,5]23>>> print(random.sample([1,'23',[4,5]],2))    #列表元素任意2个组合['23', 1]>>> item=[1,3,5,7,9]>>> random.shuffle(item)    #打乱item的顺序,相当于"洗牌">>> print(item)[7, 3, 1, 5, 9]
>>> 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))5Z126T88M
生成随机验证码

 

三 OS模块

OS模块是于操作系统交互的一个接口

import osos.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cdos.curdir  返回当前目录: ('.')os.pardir  获取当前目录的父目录字符串名:('..')os.makedirs('dirname1/dirname2')    可生成多层递归目录os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirnameos.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirnameos.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印os.remove()  删除一个文件os.rename("oldname","newname")  重命名文件/目录os.stat('path/filename')  获取文件/目录信息os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"os.linesep    输出当前平台使用的行终止符,win下为"\r\n",Linux下为"\n"os.pathsep    输出用于分割文件路径的字符串 win下为;,Linux下为:os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'os.system("bash command")  运行shell命令,直接显示os.environ  获取系统环境变量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不存在,返回Falseos.path.isabs(path)  如果path是绝对路径,返回Trueos.path.isfile(path)  如果path是一个存在的文件,返回True。否则返回Falseos.path.isdir(path)  如果path是一个存在的目录,则返回True。否则返回Falseos.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略os.path.getatime(path)  返回path所指向的文件或者目录的最后存取时间os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间os.path.getsize(path) 返回path的大小
常用方法

 

更多

>>> import os# 在Linux和Mac平台上,该函数会原样返回path,在windows平台上会将路径中所有字符转换为小写,并将所有斜杠转换为饭斜杠。>>> os.path.normcase('c:/windows\\system32\\')'c:\\windows\\system32\\'# 规范化路径,如..和/>>> os.path.normpath('c://windows\\System32\\../Temp/')'c:\\windows\\Temp'>>> a='/Users/jieli/test1/\\\a1/\\\\aa.py/../..'>>> print(os.path.normpath(a))\Users\jieli\test1

 

os路径处理#方式一:推荐使用import os,sys>>> possible_topdir = os.path.normpath(os.path.join(    os.path.abspath(os.__file__),    os.pardir,    os.pardir,    os.pardir))>>> sys.path.insert(0,possible_topdir)#方式二:不推荐使用import os>>> os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(os.__file__))))'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python'

  

 

四 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       # 返回操作系统平台名称7 sys.stdout.write('please:')8 val = sys.stdin.readline()[:-1]
#=========知识储备==========#进度条的效果[#             ][##            ][###           ][####          ]#指定宽度print('[%-15s]' %'#')print('[%-15s]' %'##')print('[%-15s]' %'###')print('[%-15s]' %'####')#打印%print('%s%%' %(100)) #第二个%号代表取消第一个%的特殊意义#可传参来控制宽度print('[%%-%ds]' %50) #[%-50s]print(('[%%-%ds]' %50) %'#')print(('[%%-%ds]' %50) %'##')print(('[%%-%ds]' %50) %'###')#=========实现打印进度条函数==========import sysimport timedef progress(percent,width=50):    if percent >= 1:        percent=1    show_str=('[%%-%ds]' %width) %(int(width*percent)*'#')    print('\r%s %d%%' %(show_str,int(100*percent)),file=sys.stdout,flush=True,end='')#=========应用==========data_size=1025recv_size=0while recv_size < data_size:    time.sleep(0.1) #模拟数据的传输延迟    recv_size+=1024 #每次收1024    percent=recv_size/data_size #接收的比例    progress(percent,width=70) #进度条的宽度70
打印进度条

 

五 shutil模块

高级的文件、文件夹、压缩包处理模块。包括复制、移动、重命名、删除等等。

shutil.copyfileobj(fsrc, fdst[, length])

将文件内容拷贝到另一个文件中

>>> import shutil>>> shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))

 

shutil.copyfile(src, dst)

拷贝文件

>>> shutil.copyfile('f1.log', 'f2.log')    #目标文件无需存在,一般不用

 

shutil.copymode(src, dst)

 仅拷贝权限。内容、组、用户均不变。

>>> shutil.copymode('f1.log', 'f2.log')    #目标文件必须存在,一般不用

 

shutil.copystat(src, dst)

仅拷贝状态的信息,包括:mode bits, atime, mtime, flags

>>> shutil.copystat('f1.log', 'f2.log')    #目标文件必须存在,一般不用

 

shutil.copy(src, dst)

拷贝文件和权限

>>> import shutil>>> shutil.copy('f1.log', 'f2.log')

 

shutil.copy2(src, dst)

拷贝文件和状态信息

>>> import shutil>>> shutil.copy2('f1.log', 'f2.log')

 

shutil.ignore_patterns(*patterns)

shutil.copytree(src, dst, symlinks=False, ignore=None)
递归的去拷贝文件夹

>>> import shutil>>> shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))    #目标目录不能存在,     注意对folder2目录父级目录要有可写权限,ignore的意思是排除
>>> import shutil>>> shutil.copytree('f1', 'f2', symlinks=True, ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))'''通常的拷贝都把软连接拷贝成硬链接,即对待软连接来说,创建新的文件'''
拷贝软连接

 

shutil.rmtree(path[, ignore_errors[, onerror]])

递归的去删除文件

>>> import shutil>>> shutil.rmtree('folder1')

 

shutil.move(src, dst)

递归的去移动文件,它类似mv命令,其实就是重命名。

>>> import shutil>>> shutil.move('folder1', 'folder3')

 

shutil.make_archive(base_name,format,...)

创建压缩包并返回文件路径,例如:zip、tar

  • base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,

     如:data_bak                        =>保存至当前路径

     如:/tmp/data_bak           =>保存至/tmp/test/

  • format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
  • root_dir: 要压缩的文件夹路径(默认当前目录)
  • owner: 用户,默认当前用户
  • group: 组,默认当前组
  • logger: 用于记录日志,通常是logging.Logger对象
#将 /data 下的文件打包放置当前程序目录>>> import shutil>>> shutil.make_archive('data_bak','tar',root_dir='/data')'/root/data_bak.tar'#将 /data下的文件打包放置 /tmp/ 目录>>> shutil.make_archive('/tmp/data_bak','tar',root_dir='/data')'/tmp/data_bak.tar'

shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:

import zipfile# 压缩z = zipfile.ZipFile('laxi.zip', 'w')z.write('a.log')z.write('data.data')z.close()# 解压z = zipfile.ZipFile('laxi.zip', 'r')z.extractall(path='.')z.close()
zipfile压缩解压缩
import tarfile# 压缩>>> t=tarfile.open('/tmp/egon.tar','w')>>> t.add('/test1/a.py',arcname='a.bak')>>> t.add('/test1/b.py',arcname='b.bak')>>> t.close()# 解压>>> t=tarfile.open('/tmp/egon.tar','r')>>> t.extractall('/egon')>>> t.close()
tarfile压缩解压缩

 

六 json & pickle模块

用于序列化的两个模块

  • json,用于字符串和python数据类型间进行转换
  • pickle,用于python特有的类型和python的数据类型间进行转换

json模块提供了四个功能:dumps、dump、loads、load

pickle模块提供了四个功能:dumps、dump、loads、load

>>> import pickle  >>> data = {
'k1':123,'k2':'Hello'} # pickle.dumps 将数据通过特殊的形式装换为只有python语言认识的字符串>>> p_str = pickle.dumps(data)>>> print(p_str)b'\x80\x03}q\x00(X\x02\x00\x00\x00k1q\x01K{X\x02\x00\x00\x00k2q\x02X\x05\x00\x00\x00Helloq\x03u.' # pickle.dump 将数据通过特殊的形式装换为只有python语言认识的字符串,并写入文件>>> with open(r'D:\result.pk','wb') as fp: pickle.dump(data,fp) #读取pickle文件>>> with open(r'D:\result.pk','rb') as fp: pickle.load(fp) {
'k2': 'Hello', 'k1': 123} >>> import json# json.dumps 将数据通过特殊的形式转换为所有程序语言都认识的字符串>>> j_str = json.dumps(data)>>> print(j_str){
"k2": "Hello", "k1": 123} # json.dumps 将数据通过特殊的形式转换为所有程序语言都认识的字符串,并写入文件>>> with open(r'D:\result.json','w') as fp: json.dump(data,fp) #读取json文件 >>> with open(r'D:\result.json','r') as fp: json.load(fp) {
'k2': 'Hello', 'k1': 123}

 

七 shelve模块

shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式,并且可以多次 dump 和 load

>>> import shelve>>> import datetime #持久化数据>>> info = {
'name': 'bigberg', 'age': 22}>>> name = ['Apoll', 'Zous', 'Luna']>>> t = datetime.datetime.now()>>> with shelve.open('/tmp/shelve.txt') as f: #执行代码后会生成3个文件:shelve.txt.bak、shelve.txt.dat、shelve.txt.dir。... f['name'] = name #持久化列表... f['info'] = info #持久化字典... f['time'] = t #持久化时间类型... #读取数据>>> with shelve.open('shelve.txt') as f: #打开文件... print(f.get('name')) #使用get获取数据... print(f.get('info'))... print(f.get('time'))...['Apoll', 'Zous', 'Luna']{
'name': 'bigberg', 'age': 22}2017-11-01 16:07:29.261414

 

八 xml模块

xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml。

xml的格式如下,就是通过<>节点来区别数据结构的:

2
2008
141100
5
2011
59900
69
2011
13600
xml数据

xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml:

print(root.iter('year'))    #全文搜索print(root.find('country'))    #在root的子节点找,只找一个print(root.findall('country'))    #在root的子节点找,找所有

 

import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml")root = tree.getroot()print(root.tag) #遍历xml文档for child in root:    print('========>',child.tag,child.attrib,child.attrib['name'])    for i in child:        print(i.tag,i.attrib,i.text) #只遍历year 节点for node in root.iter('year'):    print(node.tag,node.text)#---------------------------------------import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml")root = tree.getroot() #修改for node in root.iter('year'):    new_year=int(node.text)+1    node.text=str(new_year)    node.set('updated','yes')    node.set('version','1.0')tree.write('test.xml')  #删除nodefor country in root.findall('country'):   rank = int(country.find('rank').text)   if rank > 50:     root.remove(country) tree.write('output.xml')
View Code
#在country内添加(append)节点year2import xml.etree.ElementTree as ETtree = ET.parse("a.xml")root=tree.getroot()for country in root.findall('country'):    for year in country.findall('year'):        if int(year.text) > 2000:            year2=ET.Element('year2')            year2.text='新年'            year2.attrib={
'update':'yes'} country.append(year2) #往country节点下添加子节点tree.write('a.xml.swap')

自己创建xml文档:

import xml.etree.ElementTree as ET  new_xml = ET.Element("namelist")name = ET.SubElement(new_xml,"name",attrib={
"enrolled":"yes"})age = ET.SubElement(name,"age",attrib={
"checked":"no"})sex = ET.SubElement(name,"sex")sex.text = '33'name2 = ET.SubElement(new_xml,"name",attrib={
"enrolled":"no"})age = ET.SubElement(name2,"age")age.text = '19' et = ET.ElementTree(new_xml) #生成文档对象et.write("test.xml", encoding="utf-8",xml_declaration=True) ET.dump(new_xml) #打印生成的格式
View Code

 

九 configparser模块

用于生成和修改常见配置文档。

一个典型的Mysql配置文件如下:

[mysqld]port = 3306socket = /var/lib/mysql/mysql.sockkey_buffer = 384Mmyisam_sort_buffer_size = 64Mthread_cache_size = 8query_cache_size = 32Mmax_connections=500thread_concurrency = 8[client]user = rootpassword = 123456port = 3306socket = /var/lib/mysql/mysql.sock

 

读取

>>> import configparser>>> config=configparser.ConfigParser()>>> config.read('my.cnf')['my.cnf']#查看所有的标题>>> res=config.sections()>>> print(res)['mysqld', 'client']#判断是否存在某个标题>>> 'mysqld' in configTrue>>> print(config.has_section('mysqld'))    #同上一个True#判断标题mysqld下是否有user>>> print(config.has_option('mysqld','user'))False#查看标题client下所有key=value的key>>> options=config.options('client')>>> print(options)['user', 'password', 'port', 'socket']>>> for key in config['client']:print(key)    #同上一个... userpasswordportsocket#查看标题client下所有key=value的(key,value)格式>>> item_list=config.items('client')>>> print(item_list)[('user', 'root'), ('password', '123456'), ('port', '3306'), ('socket', '/var/lib/mysql/mysql.sock')]#查看标题client下user的值=>字符串格式>>> val=config.get('client','user')>>> print(val)root>>> config['client']['user']    #同上一个'root'#查看标题client下port的值=>整数格式>>> val1=config.getint('client','port')>>> print(val1)3306#查看标题mysqld下mysql_update的值=>布尔值格式val2=config.getboolean('mysqld','mysql_update')print(val2)#查看标题mysqld下max_connections的值=>浮点型格式val3=config.getfloat('mysqld','max_connections')print(val3)

改写

>>> import configparser>>> config=configparser.ConfigParser()>>> config.read('my.cnf',encoding='utf-8')['my.cnf']#删除整个标题client>>> config.remove_section('client')True删除标题mysqld下的key_buffer和thread_cache_size>>> config.remove_option('mysqld','key_buffer')True>>> config.remove_option('mysqld','thread_cache_size')True#添加一个标题>>> config.add_section('mysql')#在标题mysqld下添加read_buffer_size=2M,thread_concurrency=8的配置>>> config.set('mysqld','read_buffer_size','2M')>>> config.set('mysqld','thread_concurrency','8')#最后将修改的内容写入文件,完成最终的修改>>> config.write(open('my.cnf','w'))
>>> import configparser>>> config = configparser.ConfigParser()>>> config["DEFAULT"] = {
'ServerAliveInterval': '45', ... 'Compression': 'yes',... 'CompressionLevel': '9'}>>> >>> config['bitbucket.org'] = {}>>> config['bitbucket.org']['User'] = 'hg'>>> config['topsecret.server.com'] = {}>>> topsecret = config['topsecret.server.com']>>> topsecret['Host Port'] = '50022' # mutates the parser>>> topsecret['ForwardX11'] = 'no' # same here>>> config['DEFAULT']['ForwardX11'] = 'yes'>>> with open('example.ini', 'w') as configfile:... config.write(configfile)...
基于上述方法添加一个ini文档

 

十 hashlib模块

hash:一种算法 ,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

三个特点:

  1. 内容相同则hash运算结果相同,内容稍微改变则hash值则变
  2. 不可逆推
  3. 相同算法:无论校验多长的数据,得到的哈希值长度固定。
>>> import hashlib>>> m = hashlib.md5()    # m = hashlib.sha256()>>> m.update('hello'.encode('utf-8'))>>> print(m.digest())    #2进制格式hashb']A@*\xbcK*v\xb9q\x9d\x91\x10\x17\xc5\x92'>>> print(m.hexdigest())    #16进制格式hash5d41402abc4b2a76b9719d911017c592>>> m.update('alvin'.encode('utf8'))>>> print(m.hexdigest())92a7e713c30abbb0319fa07da2a5c4af>>> m2=hashlib.md5()>>> m2.update('helloalvin'.encode('utf8'))>>> print(m2.hexdigest())92a7e713c30abbb0319fa07da2a5c4af'''注意:把一段很长的数据update多次,与一次update这段长数据,得到的结果一样,但是update多次为校验大文件提供了可能。'''

 

以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。

>>> import hashlib######## 256 #########>>> hash = hashlib.sha256('898oaFs09f'.encode('utf8'))>>> hash.update('alvin'.encode('utf8'))>>> print (hash.hexdigest())e79e68f070cdedcfe63eaf1a2e92c83b4cfb1b5c6bc452d214c1b7e77cdfd1c7
import hashlibpasswds=[    'alex3714',    'alex1313',    'alex94139413',    'alex123456',    '123456alex',    'a123lex',    ]def make_passwd_dic(passwds):    dic={}    for passwd in passwds:        m=hashlib.md5()        m.update(passwd.encode('utf-8'))        dic[passwd]=m.hexdigest()    return dicdef break_code(cryptograph,passwd_dic):    for k,v in passwd_dic.items():        if v == cryptograph:            print('密码是===>\033[46m%s\033[0m' %k)cryptograph='aee949757a2e698417463d47acac93df'break_code(cryptograph,make_passwd_dic(passwds))
模拟撞库破解密码

 

python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 进行进一步的处理然后再加密

>>> import hmac>>> h = hmac.new(b'898oaFs09f','alvin'.encode('utf8'))>>> h.update('hello'.encode('utf8'))>>> print (h.hexdigest())6b1bc37749ebe91b01e07685221d38ef
#要想保证hmac最终结果一致,必须保证:#1:hmac.new括号内指定的初始key一样#2:无论update多少次,校验的内容累加到一起是一样的内容>>> import hmac>>> h1=hmac.new(b'egon')>>> h1.update(b'hello')>>> h1.update(b'world')>>> print(h1.hexdigest())f1bf38d054691688f89dcd34ac3c27f2>>> h2=hmac.new(b'egon')>>> h2.update(b'helloworld')>>> print(h2.hexdigest())f1bf38d054691688f89dcd34ac3c27f2>>> h3=hmac.new(b'egonhelloworld')>>> print(h3.hexdigest())bcca84edd9eeb86f30539922b28f3981
注意!注意!注意!

 

 

十一 subprocess模块

常用subprocess方法示例

>>> import subprocess#执行命令,返回命令执行状态 , 0 or 非0>>> retcode = subprocess.call('ls -l',shell=True)    #shell = True ,允许 shell 命令是字符串形式total 20-rw-r--r-- 1 root root 20480 Nov  1 14:13 tmp_file.tar>>> print(retcode)0>>> retcode = subprocess.call('aaa',shell=True)     #如果输入一个错误的命令,Python解释器不会提示任何信息/bin/sh: aaa: command not found     #这里是系统执行命令返回的系统报错>>> print(retcode)127#执行命令,如果命令结果为0,就正常返回,否则抛异常>>> subprocess.check_call('ls -l',shell=True)total 20-rw-r--r-- 1 root root 20480 Nov  1 14:13 tmp_file.tar0>>> subprocess.check_call('aaa',shell=True)/bin/sh: aaa: command not found     #这里是系统执行命令返回的系统报错Traceback (most recent call last):     #这里是Python解释器返回的报错  File "
", line 1, in
File "/usr/local/python3/lib/python3.6/subprocess.py", line 291, in check_call raise CalledProcessError(retcode, cmd)subprocess.CalledProcessError: Command 'aaa' returned non-zero exit status 127.#接收字符串格式命令,返回元组形式,第1个元素是执行状态,第2个是命令结果>>> subprocess.getstatusoutput('ls /bin/ls')(0, '/bin/ls')#接收字符串格式命令,并返回结果>>> subprocess.getoutput('ls /bin/ls')'/bin/ls'#执行命令,并返回结果,注意是返回结果,不是打印,下例结果返回给res>>> res=subprocess.check_output('ls -l',shell=True)>>> resb'total 20\n-rw-r--r-- 1 root root 20480 Nov 1 14:13 tmp_file.tar\n'##上面那些方法,底层都是封装的subprocess.Popenpoll()Check if child process has terminated. Returns returncodewait()Wait for child process to terminate. Returns returncode attribute.terminate() 杀掉所启动进程communicate() 等待任务结束stdin 标准输入stdout 标准输出stderr 标准错误pidThe process ID of the child process.#例子>>> p = subprocess.Popen('df -h | grep sdb1',stdin=subprocess.PIPE,stdout=subprocess.PIPE,shell=True)>>> p.stdout.read()b'/dev/sdb1 4.8G 20M 4.6G 1% /usr/local/mysql/data\n'

 

subprocess.run(...)

>>> subprocess.run('ls -l',shell=True)total 20-rw-r--r-- 1 root root 20480 Nov  1 14:13 tmp_file.tarCompletedProcess(args='ls -l', returncode=0)>>> subprocess.run('exit 1', shell=True, check=True)Traceback (most recent call last):  File "
", line 1, in
File "/usr/local/python3/lib/python3.6/subprocess.py", line 418, in run output=stdout, stderr=stderr)subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1.>>> subprocess.run('ls -l /dev/null',shell=True,stdout=subprocess.PIPE)CompletedProcess(args='ls -l /dev/null', returncode=0, stdout=b'crw-rw-rw- 1 root root 1, 3 Nov 2 09:48 /dev/null\n')

 

调用subprocess.run(...)是推荐的常用方法,在大多数情况下能满足需求,但如果你可能需要进行一些复杂的与系统的交互的话,你还可以用subprocess.Popen(),语法如下:

>>> p = subprocess.Popen('ping -c5 127.0.0.1',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)>>> print(p.stdout.read())

  

可用参数:

  • args:shell命令,可以是字符串或者序列类型(如:list,元组)
  • bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲
  • stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
  • preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
  • close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。

   所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。

  • shell:同上
  • cwd:用于设置子进程的当前目录
  • env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
  • universal_newlines:不同系统的换行符不同,True -> 同意使用 \n
  • startupinfo与createionflags只在windows下有效

     将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等

终端输入的命令分为两种:

  • 输入即可得到输出,如:ifconfig
  • 输入进行某环境,依赖再输入,如:python

需要交互的命令示例

 

十二 logging模块

       很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误、警告等信息输出。Python的logging模块提供了标准的日志接口,可以通过它存储各种格式的日志,logging的日志可以分为5个级别:

  • DEBUG    最详细的日志信息,用于问题诊断
  • INFO        信息详细程度仅次于DEBUG,通常只记录关键节点信息,用于确认一切都是按照我们预期的那样进行工作
  • WARNING    当某些不期望的事情发生时记录的信息(如,磁盘可用空间较低),但是此时应用程序还是正常运行的
  • ERROR        由于一个更严重的问题导致某些功能不能正常运行时记录的信息
  • CRITICAL     当发生严重错误,导致应用程序不能继续运行时记录的信息

说明:

  • 上面列表中的日志等级是从上到下依次升高的,即:DEBUG < INFO < WARNING < ERROR < CRITICAL,而日志的信息量是依次减少的;
  • 当为某个应用程序指定一个日志级别后,应用程序会记录所有日志级别大于或等于指定日志级别的日志信息,而不是仅仅记录指定级别的日志信息,同样,logging模块也可以指定日志记录器的日志级别,只有级别大于或等于该指定日志级别的日志记录才会被输出,小于该等级的日志记录将会被丢弃。

 

 最简单的日志输出,默认打印到终端

>>> import logging>>> logging.debug('This is a debug log.')>>> logging.info('This is a info log.')>>> logging.warning('This is a warning log.')WARNING:root:This is a warning log.>>> logging.error('This is a error log.')ERROR:root:This is a error log.>>> logging.critical('This is a critical log.')CRITICAL:root:This is a critical log.'''为什么前面两条日志没有被打印出来???这是因为logging模块提供的日志记录函数所使用的日志器设置的日志级别是WARNING,因此只有WARNING级别的日志记录以及大于它的ERROR和CRITICAL级别的日志记录被输出了,而小于它的DEBUG和INFO级别的日志记录被丢弃了。'''

 

把日志写到文件里

>>> import logging>>> logging.basicConfig(filename=r'd:\access.log',                format="%(asctime)s [%(filename)s:%(lineno)d] %(levelname)s %(message)s",                datefmt='%Y-%m-%d %H:%M:%S %p',                level=logging.INFO)>>> logging.debug('调试debug')>>> logging.info('消息info')>>> logging.warning('警告warn')>>> logging.error('错误error')>>> logging.critical('严重critical')#access.log内容:2017-11-15 14:15:09 [
:2] INFO 消息info2017-11-15 14:15:32 [
:2] WARNING 警告warn2017-11-15 14:16:15 [
:2] ERROR 错误error2017-11-15 14:16:55 [
:2] CRITICAL 严重critical

可在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:

  • filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
  • filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
  • format:指定handler使用的日志显示格式。
  • datefmt:指定日期时间格式。
  • level:设置rootlogger(后边会讲解具体概念)的日志级别
  • stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。

format参数中可能用到的格式化串

%(asctime)s          日志事件发生的时间--人类可读时间,默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒%(created)f          日志事件发生的时间--时间戳,就是当时调用time.time()函数返回的值%(relativeCreated)d  日志事件发生的时间相对于logging模块加载时间的相对毫秒数(一般不用)%(msecs)d            日志事件发生事件的毫秒部分%(levelname)s        该日志记录的文字形式的日志级别('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')%(levelno)s          该日志记录的数字形式的日志级别(10, 20, 30, 40, 50)%(name)s             所使用的日志器名称,默认是'root',因为默认使用的是 rootLogger%(message)s          用户输出的消息%(pathname)s         调用日志输出函数的模块的完整路径名,可能没有%(filename)s         调用日志输出函数的模块的文件名,包含文件后缀%(module)s           调用日志输出函数的模块名,不包含后缀%(lineno)d           调用日志输出函数的语句所在的代码行%(funcName)s         调用日志输出函数的函数名%(process)d          进程ID。可能没有%(processName)s      进程名称,Python 3.1新增%(thread)d           线程ID。可能没有%(threadName)s       线程名。可能没有
View Code

 

如果想同时把LOG打印到屏幕和文件日志里,可以使用logging模块提供的四个主要类来实现:

  1. logger  提供了应用程序可以直接使用的接口;
  2. handler   将(logger创建的)日志记录发送到合适的目的输出;
  3. filter     提供了细度设备来决定输出哪条日志记录;
  4. formatter   决定日志记录的最终输出格式。
Logger类每个程序在输出信息之前都要获得一个Logger。Logger通常对应了程序的模块名,比如聊天工具的图形界面模块可以这样获得它的Logger:LOG=logging.getLogger(”chat.gui”)而核心模块可以这样:LOG=logging.getLogger(”chat.kernel”)Logger.setLevel(lel):指定最低的日志级别,低于lel的级别将被忽略。debug是最低的内置级别,critical为最高Logger.addFilter(filt)、Logger.removeFilter(filt):添加或删除指定的filterLogger.addHandler(hdlr)、Logger.removeHandler(hdlr):增加或删除指定的handlerLogger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():可以设置的日志级别Handler类handler对象负责发送相关的信息到指定目的地。Python的日志系统有多种Handler可以使用。有些Handler可以把信息输出到控制台,有些Logger可以把信息输出到文件,还有些 Handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的Handler。可以通过addHandler()方法添加多个多handlerHandler.setLevel(lel):指定被处理的信息级别,低于lel级别的信息将被忽略Handler.setFormatter():给这个handler选择一个格式Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象每个Logger可以附加多个Handler。接下来我们就来介绍一些常用的Handler:1) logging.StreamHandler使用这个Handler可以向类似与sys.stdout或者sys.stderr的任何文件对象(file object)输出信息。它的构造函数是:StreamHandler([strm])其中strm参数是一个文件对象。默认是sys.stderr2) logging.FileHandler和StreamHandler类似,用于向一个文件输出日志信息。不过FileHandler会帮你打开这个文件。它的构造函数是:FileHandler(filename[,mode])filename是文件名,必须指定一个文件名。mode是文件的打开方式。参见Python内置函数open()的用法。默认是’a',即添加到文件末尾。3) logging.handlers.RotatingFileHandler这个Handler类似于上面的FileHandler,但是它可以管理文件大小。当文件达到一定大小之后,它会自动将当前日志文件改名,然后创建 一个新的同名日志文件继续输出。比如日志文件是chat.log。当chat.log达到指定的大小之后,RotatingFileHandler自动把 文件改名为chat.log.1。不过,如果chat.log.1已经存在,会先把chat.log.1重命名为chat.log.2。。。最后重新创建 chat.log,继续输出日志信息。它的构造函数是:RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])其中filename和mode两个参数和FileHandler一样。maxBytes用于指定日志文件的最大文件大小。如果maxBytes为0,意味着日志文件可以无限大,这时上面描述的重命名过程就不会发生。backupCount用于指定保留的备份文件的个数。比如,如果指定为2,当上面描述的重命名过程发生时,原有的chat.log.2并不会被更名,而是被删除。4) logging.handlers.TimedRotatingFileHandler这个Handler和RotatingFileHandler类似,不过,它没有通过判断文件大小来决定何时重新创建日志文件,而是间隔一定时间就 自动创建新的日志文件。重命名的过程与RotatingFileHandler类似,不过新的文件不是附加数字,而是当前时间。它的构造函数是:TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])其中filename参数和backupCount参数和RotatingFileHandler具有相同的意义。interval是时间间隔。when参数是一个字符串。表示时间间隔的单位,不区分大小写。它有以下取值:S 秒M 分H 小时D 天W 每星期(interval==0时代表星期一)midnight 每天凌晨5) logging.handlers.HTTPHandler将日志消息以GET或POST的方式发送给一个HTTP服务器6) logging.handlers.SMTPHandler将日志消息发送给一个指定的email地址7) logging.NullHandler该Handler实例会忽略error messages,通常被想使用logging的library开发者使用来避免'No handlers could be found for logger XXX'信息的出现。Filter类Filter可以被Handler和Logger用来做比level更细粒度的、更复杂的过滤功能。Filter是一个过滤器基类,它只允许某个logger层级下的日志事件通过过滤。该类定义如下:class logging.Filter(name='')    filter(record)比如,一个filter实例化时传递的name参数值为'A.B',那么该filter实例将只允许名称为类似如下规则的loggers产生的日志记录通过过滤:'A.B','A.B,C','A.B.C.D','A.B.D',而名称为'A.BB', 'B.A.B'的loggers产生的日志则会被过滤掉。如果name的值为空字符串,则允许所有的日志事件通过过滤。filter方法用于具体控制传递的record记录是否能通过过滤,如果该方法返回值为0表示不能通过过滤,返回值为非0表示可以通过过滤。Formater类Formater对象用于配置日志信息的最终顺序、结构和内容。与logging.Handler基类不同的是,应用代码可以直接实例化Formatter类。另外,如果你的应用程序需要一些特殊的处理行为,也可以实现一个Formatter的子类来完成。Formatter类的构造方法定义如下:logging.Formatter.__init__(fmt=None, datefmt=None, style='%')
详细的各类使用方法

 

logging模块就是通过这些组件来完成日志处理的,上面所使用的logging模块级别的函数也是通过这些组件对应的类来实现的

 这些组件之间的关系描述:

  • 日志器(logger)需要通过处理器(handler)将日志信息输出到目标位置,如:文件、sys.stdout、网络等;
  • 不同的处理器(handler)可以将日志输出到不同的位置;
  • 日志器(logger)可以设置多个处理器(handler)将同一条日志记录输出到不同的位置;
  • 每个处理器(handler)都可以设置自己的过滤器(filter)实现日志过滤,从而只保留感兴趣的日志;
  • 每个处理器(handler)都可以设置自己的格式器(formatter)实现同一条日志以不同的格式输出到不同的地方。

简单点说就是:日志器(logger)是入口,真正干活儿的是处理器(handler),处理器(handler)还可以通过过滤器(filter)和格式器(formatter)对要输出的日志内容做过滤和格式化等处理操作。

 

>>> import logging>>> from logging.handlers import RotatingFileHandler# 创建一个日志器logger并设置其日志级别为WARNING>>> logger = logging.getLogger('LOG')>>> logger.setLevel(logging.WARNING)# 创建一个流处理器ch_handler并设置其日志级别为DEBUG,还创建一个格式器>>> ch_handler = logging.StreamHandler()>>> ch_handler.setLevel(logging.DEBUG)>>> ch_formatter = logging.Formatter("%(asctime)s [%(filename)s:%(lineno)d] %(levelname)s %(message)s",                     datefmt='%Y-%m-%d %H:%M:%S %p')# 创建一个文件处理器fh_handler并设置其日志级别为INFO,还创建一个格式器>>> fh_handler = RotatingFileHandler(r'd:\log_test.log',maxBytes=20*1024*1024,backupCount=10)>>> fh_handler.setLevel(logging.INFO)>>> fh_formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")# 将流格式器添加到处理器ch_handler>>> ch_handler.setFormatter(ch_formatter)# 将文件格式器添加到处理器fh_handler>>> fh_handler.setFormatter(fh_formatter)#添加ch_handler和fh_handler处理器到日志器logger>>> logger.addHandler(ch_handler)>>> logger.addHandler(fh_handler)#屏幕输出>>> logger.debug('debug message')>>> logger.info('info message')>>> logger.warn('warn message')2017-11-16 15:37:03 PM [
:2] WARNING warn message>>> logger.error('error message')2017-11-16 15:37:20 PM [
:2] ERROR error message>>> logger.critical('critical message')2017-11-16 15:37:27 PM [
:2] CRITICAL critical message# log_test.log文件内容:2017-11-16 15:37:03,055 - LOG - WARNING - warn message2017-11-16 15:37:20,433 - LOG - ERROR - error message2017-11-16 15:37:27,371 - LOG - CRITICAL - critical message
将日志同时输出到文件和屏幕

 

十三 re模块

常用匹配模式(元字符)

'\w'       匹配字母数字及下划线'\W'       匹配非字母数字下划线'\s'       匹配任意空白字符,等价于 [\t\n\r\f]'\S'       匹配任意非空字符'\d'       匹配任意数字,等价于 [0-9]'\D'       匹配任意非数字'\A'       匹配字符串开始'\Z'       匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串'\z'       匹配字符串结束'\G'       匹配最后匹配完成的位置'\n'       匹配一个换行符'\t'       匹配一个制表符'^'        匹配字符串的开头'$'        匹配字符串的末尾'.'        默认匹配除换行符(\n)以外的任意字符,若指定flag DOTALL,则可以匹配包括换行符的任意字符'[...]'    用来表示一组字符,单独列出:[amk]匹配'a','m'或'k''[^...]'   不在[]中的字符:[^abc]匹配除了a,b,c之外的字符。'*'        匹配前一个字符或表达式0次或多次'+'        匹配前一个字符或表达式1次或多次'?'        匹配前一个字符或表达式1次或0次,非贪婪方式'{n}'      精确匹配前一个字符或表达式n次'{n,m}'    匹配前一个字符或表达式n次到m次,贪婪模式'a|b'      匹配a或者b'()'       匹配括号内的表达式,也表示一个

 

re.search()

 扫描整个字符串,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。

 语法格式:

re.search(pattern,string,flags=0)

 

>>> import re #常规匹配>>> result = re.search('he','hi! hello world,good')>>> print(result)<_sre.SRE_Match object at 0x020E6058>>>> print(result.group())    #获取匹配的结果he>>> print(result.span())    #获取匹配字符串的长度范围(4, 6)  # ()匹配目标>>> import re >>> result = re.search('\w+\s(\w*)','hi! hello world,good')    #为了匹配字符串中具体的目标,则需要通过()括起来>>> result.group()'hello world'>>> result.group(1)    #获取第一个括号中匹配的结果'world'>>> result.groups()    #返回的是一个元组形式('world',)  # .*贪婪匹配>>> import re >>> result = re.search('he.*(\d+).*','hi! hello 123456 world')>>> result.group(1)'6' '''从结果中可以看出只匹配到了6,并没有匹配到123456,出现这种情况的原因是前面的.* 给匹配掉了, .*在这里会尽可能的匹配多的内容,也就是我们所说的贪婪匹配'''#如果想要匹配到123456,可以把正则表达式改为:>>> result = re.search('he.*?(\d+).*','hi! hello 123456 world')  # re.S匹配模式>>> content = """hi! hello 123456 worldmy name is tbb""">>> result = re.search('he.*?(\d+).*?tbb$',content,re.S)    #用匹配模式re.S来匹配换行的内容>>> result.group()'hello 123456 world\nmy name is tbb'>>> print(result.group())hello 123456 worldmy name is tbb>>> print(result.group(1))123456  # \转义>>> import re >>> content = 'hello! price is $5.00'>>> result = re.search('price is \$5\.00',content)>>> print(result.group())price is $5.00 #如果要匹配\,可以使用如下方法:>>> re.search(r'a\\c','a\c').group()    #r代表告诉解释器使用rawstring,即原生字符串,把我们正则内的所有符号都当普通字符处理,不要转义'a\\c'或>>> re.search('a\\\\c','a\c').group()'a\\c' '''当我们要匹配的内容中存在特殊字符的时候,就需要用到转移符号\'''

 

re.match()

尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配的话,match()就会返回None

同search,不过在字符串开始处进行匹配,完全可以用search+^代替match,如下所示:

>>> result = re.match('world','hello world')>>> print(result)None>>> result = re.search('world','hello world')>>> print(result)<_sre.SRE_Match object; span=(6, 11), match='world'>>>> result = re.search('^world','hello world')>>> print(result)None

  

re.findall()

搜索字符串,以列表的形式返回全部能匹配的子串

 

>>> re.findall('a[+*(]b','a*b a+b a-b a=b')['a*b', 'a+b']

 

re.split()

>>> re.split('[ab]','abcd')    #先按'a'分割得到''和'bcd',再对''和'bcd'分别按'b'分割['', '', 'cd']

 

re.sub()

替换字符串中每一个匹配的子串后返回替换后的字符串

re.sub(正则表达式,替换成的字符串,原字符串)

 

>>> re.sub('l','L','hello world')    #不指定n,默认替换所有'heLLo worLd'>>> re.sub('l','L','hello world',1)'heLlo world'>>> re.sub('l','L','hello world',2)'heLLo world'>>> re.sub('(\d+)',r'\1 7890','hello 123456 world')    #获取匹配的字符串后面添加些内容,\1是获取第一个匹配的结果。为了防止转义字符的问题,需要在前面加上r'hello 123456 7890 world'>>> re.sub('(\w*)(\s*)(\d+)(\s*)(\w*)',r'\5\4\3\2\1','hello 123456 world')    #把匹配到的结果按照顺序对原有字符串进行组合,返回新的字符串'world 123456 hello'>>> re.subn('l','L','hello world')    #结果带有总共替换的个数('heLLo worLd', 3)

 

 re.compile()

将正则表达式编译成正则表达式对象,方便复用该正则表达式

>>> content = 'hello 123456 world'>>> obj = re.compile('\d{3}')>>> obj.search(content).group()'123'>>> obj.findall(content)    #重用了obj['123', '456']

 

对上面的一个小结:

尽量使用泛匹配,使用括号得到匹配目标,尽量使用非贪婪模式,有换行符就用re.S
强调re.match是从字符串的起始位置匹配一个模式

转载于:https://www.cnblogs.com/cyfiy/p/7754284.html

你可能感兴趣的文章
P1107 最大整数
查看>>
多进程与多线程的区别
查看>>
Ubuntu(虚拟机)下安装Qt5.5.1
查看>>
java.io.IOException: read failed, socket might closed or timeout, read ret: -1
查看>>
java 常用命令
查看>>
CodeForces Round #545 Div.2
查看>>
卷积中的参数
查看>>
51nod1076 (边双连通)
查看>>
Item 9: Avoid Conversion Operators in Your APIs(Effective C#)
查看>>
深入浅出JavaScript(2)—ECMAScript
查看>>
STEP2——《数据分析:企业的贤内助》重点摘要笔记(六)——数据描述
查看>>
ViewPager的onPageChangeListener里面的一些方法参数:
查看>>
Jenkins关闭、重启,Jenkins服务的启动、停止方法。
查看>>
CF E2 - Array and Segments (Hard version) (线段树)
查看>>
Linux SPI总线和设备驱动架构之四:SPI数据传输的队列化
查看>>
SIGPIPE并产生一个信号处理
查看>>
CentOS
查看>>
Linux pipe函数
查看>>
java equals 小记
查看>>
爬虫-通用代码框架
查看>>