一、PYTHON常用模块学习
1.什么是模块
在python中,一个.py文件就称之为一个模块
2.使用模块的优点
1)大大提高代码的可维护性,编写代码不必从零开始
2)避免函数名和变量名冲突
3.模块的分类
1)内置标准模块
2)第三方开源模块
3)自义定模块
4.模块调用
'''
1)import module
2)form module import xx
3)from module.xx.xx import xx as rename
4)from module.xx.xx import *
'''
5.包
一个文件夹管理多个模块文件,这个文件夹就被称为包
导入的栗子:
form my_proj.crm import views
views.sayhi() #在my_proj文件下的crm文件夹里导入views的.py文件
相对导入
from . import xx # . 就是相对导入
def....
在涉及到相对导入的时候,package所对应的文件夹必须正确的被pyrhon解释器视作package,而不是普通文件夹,需要满足两个条件:
1.文件夹中必须有--init--.py
2.不能作为顶层模块来执行该文件夹中的py文件(即不能作为主函数的入口)
6.time模块的方法
1)time.localtime([secs]) :
将一个时间戳转换为当前时区的struct_time,secs参数未提供,则以当前时间为准
2)time.gmtime([secs]) :
和localtime()方法类似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。
3)time.time() :
返回当前时间戳
4)time.mktime(t) :
将一个struct_time转换为时间戳
5)time.sleep(secs) :
线程推迟指定的时间运行,单位为秒
6)time.asctime([t]) :
把一个表示时间的元组或者struct_time表示为这种形式:'sun oct 1 12:04:38 2017'。如果没有参数,将会将time.localtime()作为参数传入。
7)time.ctime([secs]) :
把一个时间戳(按秒计算的浮点数)转化为time.astime()形式。如果参数未给或者为None的时候,将会默认time.time为参数。它的作用相当于time.astime(time.localtime(secs))
8)time.strftime(format[,t]) :
把一个代表时间的元组或者struct_time(如由time.localtime()和time.gmtime()返回)转化为格式化的时间字符串。如果t未指定,将传入time.lacaltime()
栗子
time.strftime('%Y-%m-%d %X,time.localtime()) #输出‘2017-10-01 12:14:23'
9)time.strptime(string[,format]) :
把一个格式化时间字符串转化为struct_time。实际上它和strftime()是逆操作
栗子
time.strptime('2017-10-3 17:54',%Y-%m-%d %H:%M') #输出time.struct_time(tm_year=2017,tm_mon=10,tm_mday=3,tm_hour=17,tm_min=54,tm_sec=0,tm_wday=1,tm_yday=276,tm_isdst=-1)
7.datetime模块
只需要记住以下方法
1)d=datetime.datetime.now()
返回当前的datetime日期类型
2)datetime.date.fromtimestamp(32222)
把一个时间戳转为datetime日期类型
3)时间换算
datetime.datetime.now() + detetime.timedelta(4) #输出的时间为当前时间+4天
datetime.datetime.now()+detetime.timedelta(hours=4) # +4小时
4)时间替换
d.replace(year=1996,mouth=11,day=30)
detetime.date(1996,11,30)
8.random模块
1)random.randint(1,100)
传入两个参数1和100,从1到100里随机取一个数
2)random.range(1,100)
和1一样,区别是1可以包含100
3)random.random()
返回一个随机浮点数
4)random.sample('abcdefghij',3)
从多个字符选出3个字符
5)random.choice('abce3#s@1')
返回一个给定数据集合的随机字符
6)洗牌
a = [0,1,2,3,4]
random.shuffle(a)
#输出a会是打乱的列表
7)生成随机字符
' '.join(random.sample(s,5)) #输出随机字符
s代表一个列表,5代表5位
9.OS模块
1)得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd()
返回指定目录下的所有文件和目录名:os.listdir()
2)函数用来删除一个文件:os.remove()
3)删除多个目录:os.removedirs(r“c:\python”)
4)检验给出的路径是否是一个文件:os.path.isfile()
5)检验给出的路径是否是一个目录:os.path.isdir()
6)判断是否是绝对路径:os.path.isabs()
7)检验给出的路径是否真地存:os.path.exists()
8)返回一个路径的目录名和文件名:os.path.split() e.g os.path.split('/home/swaroop/byte/code/poem.txt') 结果:('/home/swaroop/byte/code', 'poem.txt')
9)分离扩展名:os.path.splitext() e.g os.path.splitext('/usr/local/test.py') 结果:('/usr/local/test', '.py')
10)获取路径名:os.path.dirname()
11)获得绝对路径: os.path.abspath()
12)获取文件名:os.path.basename()
13)运行shell命令: os.system()
14)读取操作系统环境变量HOME的值:os.getenv("HOME")
15)返回操作系统所有的环境变量: os.environ
16)设置系统环境变量,仅程序运行时有效:os.environ.setdefault('HOME','/home/alex')
17)给出当前平台使用的行终止符:os.linesep Windows使用'\r\n',Linux and MAC使用'\n'
18)指示你正在使用的平台:os.name 对于Windows,它是'nt',而对于Linux/Unix用户,它是'posix'
19)重命名:os.rename(old, new)
20)创建多级目录:os.makedirs(r“c:\python\test”)
21)创建单个目录:os.mkdir(“test”)
22)获取文件属性:os.stat(file)
23)修改文件权限与时间戳:os.chmod(file)
24)获取文件大小:os.path.getsize(filename)
25)结合目录名与文件名:os.path.join(dir,filename)
26)改变工作目录到dirname: os.chdir(dirname)
27)获取当前终端的大小: os.get_terminal_size()
28)杀死进程: os.kill(10884,signal.SIGKILL)
10.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:') #标准输出 , 引出进度条的例子, 注,在py3上不行,可以用print代替
8)val = sys.stdin.readline()[:-1] #标准输入
9)sys.getrecursionlimit() #获取最大递归层数
10)sys.setrecursionlimit(1200) #设置最大递归层数
11)sys.getdefaultencoding() #获取解释器默认编码
12)sys.getfilesystemencoding #获取内存数据存到文件里的默认编码
11.shutil模块
高级的 文件、文件夹、压缩包 处理模块
1)shutil.copyfileobj(fsrc, fdst[, length])
将文件内容拷贝到另一个文件中
2)import shutil
shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))
shutil.copyfile(src, dst)
拷贝文件
3)shutil.copyfile('f1.log', 'f2.log') #目标文件无需存在
shutil.copymode(src, dst)
仅拷贝权限。内容、组、用户均不变
4)shutil.copymode('f1.log', 'f2.log') #目标文件必须存在
shutil.copystat(src, dst)
仅拷贝状态的信息,包括:mode bits, atime, mtime, flags
5)shutil.copystat('f1.log', 'f2.log') #目标文件必须存在
shutil.copy(src, dst)
拷贝文件和权限
6)import shutil
shutil.copy('f1.log', 'f2.log')
shutil.copy2(src, dst)
拷贝文件和状态信息
7)import shutil
shutil.copy2('f1.log', 'f2.log')
shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
递归的去拷贝文件夹
8)import shutil
shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('.pyc', 'tmp')) #目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除
shutil.rmtree(path[, ignore_errors[, onerror]])
递归的去删除文件
9)import shutil
shutil.rmtree('folder1')
shutil.move(src, dst)
递归的去移动文件,它类似mv命令,其实就是重命名。
10)import shutil
shutil.move('folder1', 'folder3')
shutil.make_archive(base_name, format,...)
创建压缩包并返回文件路径,例如:zip、tar
创建压缩包并返回文件路径,例如:zip、tar
base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如 data_bak =>保存至当前路径
如:/tmp/data_bak =>保存至/tmp/
format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
root_dir: 要压缩的文件夹路径(默认当前目录)
owner: 用户,默认当前用户
group: 组,默认当前组
logger: 用于记录日志,通常是logging.Logger对象
将 /data 下的文件打包放置当前程序目录
import shutil
ret = shutil.make_archive("data_bak", 'gztar', root_dir='/data')
将 /data下的文件打包放置 /tmp/目录
import shutil
ret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data')
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:
zipfile压缩&解压缩
11)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()
tarfile压缩&解压缩
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()
12.序列化
序列化是指把内存里的数据类型转变成字符串,以使其能存储到硬盘或通过网络传输到远程,因为硬盘或网络传输时只能接受bytes
用于序列化的两个模块:
1)json,用于字符串 和 python数据类型间进行转换,Json模块提供了四个功能:dumps、dump、loads、load
优点:跨语言、体积小
缺点:只能支持int\str\list\tuple\dict
2)pickle,用于python特有的类型 和 python的数据类型间进行转换,pickle模块提供了四个功能:dumps、dump、loads、load
优点:专为python设计,支持python所有的数据类型
缺点:只能在python中使用,存储数据占空间大
13.shelve模块
shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式
序列化:
import shelve
f = shelve.open('shelve_test') #打开一个文件
names = ["alex", "rain", "test"]
info = {'name':'alex','age':22}
f["names"] = names #持久列表化
f['info_dic'] = info
f.close()
反序列化:
import shelve
d = shelve.open('shelve_test')
print(d['names'])
print(d['info_dic'])
# del d['test'] 还可以删除
14.xml模块
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单
xml的格式如下
2
2008
141100
5
2011
59900
69
2011
13600
xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml
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)
for i in child:
print(i.tag,i.text)
#只遍历year 节点
for node in root.iter('year'):
print(node.tag,node.text)
修改和删除xml文档内容:
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")
tree.write("xmltest.xml")
#删除node
for country in root.findall('country'):
rank = int(country.find('rank').text)
if rank > 50:
root.remove(country)
tree.write('output.xml')
自己创建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) #打印生成的格式
15.configparser模块
此模块用于生成和修改常见配置文档,当前模块的名称在 python 3.x 版本中变更为 configparser。
软件的常见配置文件格式如下:
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
[bitbucket.org]
User = hg
[topsecret.server.com]
Port = 50022
ForwardX11 = no
解析配置文件
>>> import configparser # 导入模块
>>> config = configparser.ConfigParser() #实例化(生成对象)
>>> config.sections() #调用sections方法
[]
>>> config.read('example.ini') # 读配置文件(注意文件路径)
['example.ini']
>>> config.sections() #调用sections方法(默认不会读取default)
['bitbucket.org', 'topsecret.server.com']
>>> 'bitbucket.org' in config #判断元素是否在sections列表内
True
>>> 'bytebong.com' in config
False
>>> config['bitbucket.org']['User'] # 通过字典的形式取值
'hg'
>>> config['DEFAULT']['Compression']
'yes'
>>> topsecret = config['topsecret.server.com']
>>> topsecret['ForwardX11']
'no'
>>> topsecret['Port']
'50022'
>>> for key in config['bitbucket.org']: print(key) # for循环 bitbucket.org 字典的key
...
user
compressionlevel
serveraliveinterval
compression
forwardx11
>>> config['bitbucket.org']['ForwardX11']
'yes'
其它增删改查语法
[group1] # 支持的两种分隔符“=”, “:”
k1 = v1
k2:v2
[group2]
k1 = v1
import ConfigParser
config = ConfigParser.ConfigParser()
config.read('i.cfg')
# ########## 读 ##########
#secs = config.sections()
#print(secs)
#options = config.options('group2') # 获取指定section的keys
#print(options)
#item_list = config.items('group2') # 获取指定 section 的 keys & values ,key value 以元组的形式
#print(item_list)
#val = config.get('group1','key') # 获取指定的key 的value
#val = config.getint('group1','key')
# ########## 改写 ##########
#sec = config.remove_section('group1') # 删除section 并返回状态(true, false)
#config.write(open('i.cfg', "w")) # 对应的删除操作要写入文件才会生效
#sec = config.has_section('wupeiqi')
#sec = config.add_section('wupeiqi')
#config.write(open('i.cfg', "w")) #
#config.set('group2','k1',11111)
#config.write(open('i.cfg', "w"))
#config.remove_option('group2','age')
#config.write(open('i.cfg', "w"))
16.hashlib模块
1)HASH
Hash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。
简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
HASH主要用于信息安全领域中加密算法,他把一些不同长度的信息转化成杂乱的128位的编码里,叫做HASH值.也可以说,hash就是找到一种数据内容和数据存放地址之间的映射关系
2)MD5
什么是MD5算法
MD5讯息摘要演算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码杂凑函数,可以产生出一个128位的散列值(hash value),用于确保信息传输完整一致。MD5的前身有MD2、MD3和MD4。
MD5功能
输入任意长度的信息,经过处理,输出为128位的信息(数字指纹);
不同的输入得到的不同的结果(唯一性);
MD5算法的特点
压缩性:任意长度的数据,算出的MD5值的长度都是固定的
容易计算:从原数据计算出MD5值很容易
抗修改性:对原数据进行任何改动,修改一个字节生成的MD5值区别也会很大
强抗碰撞:已知原数据和MD5,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
MD5算法是否可逆?
MD5不可逆的原因是其是一种散列函数,使用的是hash算法,在计算过程中原文的部分信息是丢失了的。
MD5用途
防止被篡改:
比如发送一个电子文档,发送前,我先得到MD5的输出结果a。然后在对方收到电子文档后,对方也得到一个MD5的输出结果b。如果a与b一样就代表中途未被篡改。
比如我提供文件下载,为了防止不法分子在安装程序中添加木马,我可以在网站上公布由安装文件得到的MD5输出结果。
SVN在检测文件是否在CheckOut后被修改过,也是用到了MD5.
防止直接看到明文:
现在很多网站在数据库存储用户的密码的时候都是存储用户密码的MD5值。这样就算不法分子得到数据库的用户密码的MD5值,也无法知道用户的密码。(比如在UNIX系统中用户的密码就是以MD5(或其它类似的算法)经加密后存储在文件系统中。当用户登录的时候,系统把用户输入的密码计算成MD5值,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这不但可以避免用户的密码被具有系统管理员权限的用户知道,而且还在一定程度上增加了密码被破解的难度。)
防止抵赖(数字签名):
这需要一个第三方认证机构。例如A写了一个文件,认证机构对此文件用MD5算法产生摘要信息并做好记录。若以后A说这文件不是他写的,权威机构只需对此文件重新产生摘要信息,然后跟记录在册的摘要信息进行比对,相同的话,就证明是A写的了。这就是所谓的“数字签名”。
3)SHA-1
安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。
SHA是美国国家安全局设计的,由美国国家标准和技术研究院发布的一系列密码散列函数。
由于MD5和SHA-1于2005年被山东大学的教授王小云破解了,科学家们又推出了SHA224, SHA256, SHA384, SHA512,当然位数越长,破解难度越大,但同时生成加密的消息摘要所耗时间也更长。目前最流行的是加密算法是SHA-256 .
4)MD5与SHA-1比较
由于MD5与SHA-1均是从MD4发展而来,它们的结构和强度等特性有很多相似之处,SHA-1与MD5的最大区别在于其摘要比MD5摘要长32 比特。对于强行攻击,产生任何一个报文使之摘要等于给定报文摘要的难度:MD5是2128数量级的操作,SHA-1是2160数量级的操作。产生具有相同摘要的两个报文的难度:MD5是264是数量级的操作,SHA-1 是280数量级的操作。因而,SHA-1对强行攻击的强度更大。但由于SHA-1的循环步骤比MD5多80:64且要处理的缓存大160比特:128比特,SHA-1的运行速度比MD5慢。
5)Python里提供的模块
主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
import hashlib
m = hashlib.md5()
m.update(b"Hello")
m.update(b"It's me")
print(m.digest())
m.update(b"It's been a long time since last time we ...")
print(m.digest()) #2进制格式hash
print(len(m.hexdigest())) #16进制格式hash
'''
def digest(self, *args, **kwargs): # real signature unknown
""" Return the digest value as a string of binary data. """
pass
def hexdigest(self, *args, **kwargs): # real signature unknown
""" Return the digest value as a string of hexadecimal digits. """
pass
'''
import hashlib
# ######## md5 ########
hash = hashlib.md5()
hash.update('admin')
print(hash.hexdigest())
# ######## sha1 ########
hash = hashlib.sha1()
hash.update('admin')
print(hash.hexdigest())
# ######## sha256 ########
hash = hashlib.sha256()
hash.update('admin')
print(hash.hexdigest())
# ######## sha384 ########
hash = hashlib.sha384()
hash.update('admin')
print(hash.hexdigest())
# ######## sha512 ########
hash = hashlib.sha512()
hash.update('admin')
print(hash.hexdigest())
17.subprocess模块
1)run()方法
标准写法
subprocess.run(['df','-h'],stderr=subprocess.PIPE,stdout=subprocess.PIPE,check=True)
涉及到管道|的命令需要这样写
subprocess.run('df -h|grep disk1',shell=True) #shell=True的意思是这条命令直接交给系统去执行,不需要python负责解析
2)call()方法
#执行命令,返回命令执行状态 , 0 or 非0
>>> retcode = subprocess.call(["ls", "-l"])
#执行命令,如果命令结果为0,就正常返回,否则抛异常
>>> subprocess.check_call(["ls", "-l"])
0
#接收字符串格式命令,返回元组形式,第1个元素是执行状态,第2个是命令结果
>>> subprocess.getstatusoutput('ls /bin/ls')
(0, '/bin/ls')
#接收字符串格式命令,并返回结果
>>> subprocess.getoutput('ls /bin/ls')
'/bin/ls'
#执行命令,并返回结果,注意是返回结果,不是打印,下例结果返回给res
>>> res=subprocess.check_output(['ls','-l'])
>>> res
b'total 0\ndrwxr-xr-x 12 alex staff 408 Nov 2 11:05 OldBoyCRM\n'
3)popen()方法
常用参数:
args:shell命令,可以是字符串或者序列类型(如:list,元组)
stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
shell:同上
cwd:用于设置子进程的当前目录
env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
下面这2条语句执行会有什么区别?
a=subprocess.run('sleep 10',shell=True,stdout=subprocess.PIPE)
a=subprocess.Popen('sleep 10',shell=True,stdout=subprocess.PIPE)
区别是Popen会在发起命令后立刻返回,而不等命令执行结果。这样的好处是什么呢?
如果你调用的命令或脚本 需要执行10分钟,你的主程序不需卡在这里等10分钟,可以继续往下走,干别的事情,每过一会,通过一个什么方法来检测一下命令是否执行完成就好了。
Popen调用后会返回一个对象,可以通过这个对象拿到命令执行结果或状态等,该对象有以下方法
poll()
Check if child process has terminated. Returns returncode
wait()
Wait for child process to terminate. Returns returncode attribute.
terminate()终止所启动的进程Terminate the process with SIGTERM
kill() 杀死所启动的进程 Kill the process with SIGKILL
communicate()与启动的进程交互,发送数据到stdin,并从stdout接收输出,然后等待任务结束
>>> a = subprocess.Popen('python3 guess_age.py',stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE,shell=True)
>>> a.communicate(b'22')
(b'your guess:try bigger\n', b'')
18.logging模块
python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging的日志可以分为 debug(), info(), warning(), error() and critical()5个级别
最简单的用法
import logging
logging.warning("user [alex] attempted wrong password more than 3 times")
logging.critical("server is down")
输出
WARNING:root:user [alex] attempted wrong password more than 3 times
CRITICAL:root:server is down
把日志写到文件里
import logging
logging.basicConfig(filename='example.log',level=logging.INFO)
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')
19.re模块
常用表达式
'.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
'^' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
'$' 匹配字符结尾, 若指定flags MULTILINE ,re.search('foo.$','foo1\nfoo2\n',re.MULTILINE).group() 会匹配到foo1
'*' 匹配*号前的字符0次或多次, re.search('a*','aaaabac') 结果'aaaa'
'+' 匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']
'?' 匹配前一个字符1次或0次 ,re.search('b?','alex').group() 匹配b 0次
'{m}' 匹配前一个字符m次 ,re.search('b{3}','alexbbbs').group() 匹配到'bbb'
'{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|45)", "abcabca456c").group() 结果为'abcabca45'
'\A' 只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的,相当于re.match('abc',"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...)' 分组匹配 re.search("(?P[0-9]{4})(?P[0-9]{2})(?P[0-9]{4})","371481199306143242").groupdict("city") 结果{'province': '3714', 'city': '81', 'birthday': '1993'}
re的匹配语法有以下几种:
re.match 从头开始匹配
re.search 匹配包含
re.findall 把所有匹配到的字符放到以列表中的元素返回
re.split 以匹配到的字符当做列表分隔符
re.sub 匹配字符并替换
re.fullmatch 全部匹配
20.项目代码规范
目录组织方式
假设你的项目名为foo, 我比较建议的最方便快捷目录结构这样就足够了:
Foo/
|-- bin/
| |-- foo
|
|-- foo/
| |-- tests/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
|
|-- docs/
| |-- conf.py
| |-- abc.rst
|
|-- setup.py
|-- requirements.txt
|-- README
bin/: 存放项目的一些可执行文件,当然你可以起名script/之类的也行。
foo/: 存放项目的所有源代码。(1) 源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。(2) 其子目录tests/存放单元测试代码; (3) 程序的入口最好命名为main.py。
docs/: 存放一些文档。
setup.py: 安装、部署、打包的脚本。
requirements.txt: 存放软件依赖的外部Python包列表。
README: 项目说明文件。