为什么会有模块

Python不仅有自带的模块(称之为标准库),还有海量的第三方模块,并且很多开发者还在不断贡献自己开发的新模块,正是有了这么强大的“模块自信”,Python才被很多人钟爱。并且这种方式也正在不断被其他更多语言所借鉴,几乎成为普世行为了

初识模块

  • sys 模块
1
2
3
import math

math.pow(3,2)

这里的math(是Python标准库之一)就是一个模块,用import引入这个模块,然后可以使用模块里面的函数,比如pow()函数。显然,这里是不需要自己动手写具体函数的,我们的任务就是拿过来使用。这就是模块的好处:拿过来就用,不用自己重写

模块的定义

“模块是程序”一语道破了模块的本质,它就是一个扩展名为.py的Python程序

我们能够在应该使用它的时候将它引用过来,节省精力,不需要重写雷同的代码

包和库以及模块的概念和关系

顾名思义,包和库都是比“模块”大的。一般来讲,一个“包”里面会有多个模块,当然,“库”是一个更大的概念了,比如Python标准库中的每个库都有好多个包,每个包都有若干个模块。一个包由多个模块组成,即有多个.py的文件,那这个所谓的“包”其实就是我们熟悉的一个目录罢了。

如何解决引用某个目录中的模块问题?

解决方法就是在该目录中放一个__init__.py文件。__init__.py是一个空文件,将它放在某个目录中,就可以将该目录中的其他.py文件作为模块被引用

例如,建立一个目录,名曰:package_test,里面依次放了pm.py和pp.py两个文件,然后建立一个空文件__init__.py,接下来,需要导入这个包(package_test)中的模块

1
2
3
4
5
>>> import package_qi.pm

>>> package_qi.pm.lang()

'python'

或者

1
2
3
4
5
>>> from package_qi import pm

>>> pm.lang()

'python'

其实总结一下,导入模块的几种方法

1
2
3
4
import module
from module.xx.xx import xx
from module.xx.xx import xx as rename
from module.xx.xx import *

导入模块其实就是告诉Python解释器去解释那个py文件

  • 导入一个py文件,解释器解释该py文件
  • 导入一个包,解释器解释该包下的 init.py 文件 【py2.7】

那么问题来了,导入模块时是根据那个路径作为基准来进行的呢?即:sys.path

1
2
3
import sys

print(sys.path)

模块的分类

  1. 自定义模块
  2. 内置模块
  3. 第三方模块

自定义模块

其实所谓的自定义模块,就是自己创建一个.py文件,然后导入到你想使用的地方即可

那如果sys.path路径列表没你想要的路径,可以通过 sys.path.append(‘路径’) 添加

1
2
3
4
import sys
import os
project_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(project_path)

内置模块

1. sys

用于对python解释器系统级别的模块

1
2
3
4
5
6
7
8
sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时exit(0)
sys.version 获取Python解释程序的版本信息
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
sys.stdin 输入相关
sys.stdout 输出相关
sys.stderror 错误相关

进度百分比

1
2
3
4
5
6
7
import sys,time

# 进度条的演示案例
for i in range(20):
sys.stdout.write("#")
sys.stdout.flush()
time.sleep(0.2)
2. os
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
os.getcwd()                 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd
os.curdir 返回当前目录: ('.')
os.pardir 获取当前目录的父目录字符串名:('..')
os.makedirs('dir1/dir2') 可生成多层递归目录
os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() 删除一个文件
os.rename("oldname","new") 重命名文件/目录
os.stat('path/filename') 获取文件/目录信息
os.sep 操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep 当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep 用于分割文件路径的字符串
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不存在,返回False
os.path.isabs(path) 如果path是绝对路径,返回True
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所指向的文件或者目录的最后修改时间
3. random
1
2
3
4
import random
print random.random()
print random.randint(1,2)
print random.randrange(1,10)

生成随机验证码

1
2
3
4
5
6
7
8
9
10
import random
checkcode = ''
for i in range(4):
current = random.randrange(0,4)
if current != i:
temp = chr(random.randint(65,90))
else:
temp = random.randint(0,9)
checkcode += str(temp)
print checkcode
4. 序列化

现有如下的需求,需要将下面的字典存入到磁盘中,怎么办?

1
2
3
4
info = {
"name":'zhangsan',
"age":25
}

将这个字典存入到文件中不就完了

于是,我们打开一个文件,将上面的字典存入到一个文件中

于是,有了如下的代码,但是我们发现一个问题:

1
2
3
f = open('data.json',"w")
f.write(str(info))
f.close()

存入到文件中的 是一个字符串,我们采用下面的方法取出数据:

1
2
3
4
f = open("data.json","r")
data = eval( f.read() )
print(data)
f.close()

这个时候我们再去取name和age的时候,很方便取出来了

但是有一个问题,如果我们这个时候用python写了一个接口给php使用,接口里面的内容就是使用上述方法将字典保存到文件中,那此时php想获取值得时候,发现没有eval这个函数,那php怎么去取?

因此,上面的思路已经不能满足我们的需求了,那该怎么办?

我们采用json模块来进行存储

因此,我们有如下的代码:

1
2
3
4
5
# 此处调用的是json的dumps方法
data = json.dumps(info)

with open("data2.json","w") as f:
f.write(data)

这个时候,我们存入的就是一个标准的json格式

取出的时候,我们用如下的代码:

1
2
3
4
5
with open("data2.json","r") as f:
# 采用loads方法
data = json.loads(f.read())
print(data)
print(data['name'])

除了上述的dumps和loads方法之外,还有两个方法:

dump 和 load

dump的用法:

1
2
3
4
f = open("data3.json","w")

data = json.dump(info,f)
print(data)

load的用法:

1
2
3
f = open('data3.json',"r")
data = json.load(f)
print(data['age'])

上述的过程就叫做

序列化—–即把一个内存对象转换成字符串的过程
反序列化—将一个字符串转换成对应内存对象的过程

为啥会有上述的操作?

持久化内存对象
有的时候我们需要保存我们可能要中断的执行任务 需要恢复上次执行的环境场景
所以我们需要把一个内存对象持久化存入到磁盘中,因为内存对象不容易存到数据库
例子:打游戏时需要恢复场景,虚拟机挂起等

在python中,除了json可以进行序列化和返序列化之外,还有一个特定的模块pickle,也可以进行序列化和反序列化

我们需要注意的是,json和pickle最终的结果都是一样的,那还要pickle干啥?

pickle的存在是用来序列化和反序列化一些特有的类型,比如函数

pickle和json的区别?

1.pickle能够序列化python中的所有数据类型,而json只能够序列化基本的数据类型
2.pickle是python独有的,只能是用于python中,不能用于和其他语言交换数据

Python中用于序列化的两个模块

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

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


5. logging模块

主要用来记录程序的各种错误和运行信息,方便后续调试

  • 记录单文件日志
1
2
3
4
5
6
7
8
9
10
11
12
13
import logging

logging.basicConfig(filename='test.log',
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
level=10)

logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')
logging.log(10,'log')

日志等级

1
2
3
4
5
6
7
8
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0

注:只有【当前写等级】大于【日志等级】时,日志文件才被记录

日志格式化

日志格式.png

  • 多文件日志

对于上述记录日志的功能,只能将日志记录在单文件中,如果想要设置多个日志文件,logging.basicConfig将无法完成,需要自定义文件和日志操作对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 定义文件
file_1_1 = logging.FileHandler('l1_1.log', 'a', encoding='utf-8')
fmt = logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s")
file_1_1.setFormatter(fmt)

file_1_2 = logging.FileHandler('l1_2.log', 'a', encoding='utf-8')
fmt = logging.Formatter()
file_1_2.setFormatter(fmt)

# 定义日志
logger1 = logging.Logger('s1', level=logging.ERROR)
logger1.addHandler(file_1_1)
logger1.addHandler(file_1_2)


# 写日志
logger1.critical('1111')
1
2
3
4
5
6
7
8
9
10
11
# 定义文件
file_2_1 = logging.FileHandler('l2_1.log', 'a')
fmt = logging.Formatter()
file_2_1.setFormatter(fmt)

# 定义日志
logger2 = logging.Logger('s2', level=logging.INFO)
logger2.addHandler(file_2_1)

# 写日志
logger1.critical('2222')

如上述创建的两个日志对象

  • 当使用【logger1】写日志时,会将相应的内容写入 l1_1.log 和 l1_2.log
  • 当使用【logger2】写日志时,会将相应的内容写入 l2_1.log
6. time

时间相关的操作,时间有三种表示方式:

时间戳 1970年1月1日之后的秒,即:time.time()
格式化的字符串 2014-11-11 11:11, 即:time.strftime(‘%Y-%m-%d’)
结构化时间 元组包含了:年、日、星期等 time.struct_time 即:time.localtime()

常见的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import time

print(time.altzone) #返回与utc时间的时间差,以秒计算
print(time.asctime()) #返回时间格式"Fri Aug 19 11:14:16 2016",
print(time.localtime()) #返回本地时间 的struct time对象格式
print(time.gmtime(time.time()-800000)) #返回utc时间的struc时间对象格式

print(time.asctime(time.localtime())) #返回时间格式"Fri Aug 19 11:14:16 2016",
print(time.ctime()) #返回Fri Aug 19 12:38:29 2016 格式, 同上


# 日期字符串 转成 时间戳
string_to_struct = time.strptime("2016/05/22","%Y/%m/%d") #将 日期字符串 转成 struct时间对象格式
print(string_to_struct)
#
struct_to_stamp = time.mktime(string_to_struct) #将struct时间对象转成时间戳
print(struct_to_stamp)


#时间戳 转为 日期字符串
print(time.gmtime(time.time()-86640)) #将utc时间戳转换成struct_time格式
print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) ) #将utc struct_time格式转成指定的字符串格式


#时间加减
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分

J4uxSK.png

占位符号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
%Y  Year with century as a decimal number.
%m Month as a decimal number [01,12].
%d Day of the month as a decimal number [01,31].
%H Hour (24-hour clock) as a decimal number [00,23].
%M Minute as a decimal number [00,59].
%S Second as a decimal number [00,61].
%z Time zone offset from UTC.
%a Locale's abbreviated weekday name.
%A Locale's full weekday name.
%b Locale's abbreviated month name.
%B Locale's full month name.
%c Locale's appropriate date and time representation.
%I Hour (12-hour clock) as a decimal number [01,12].
%p Locale's equivalent of either AM or PM.
7. 加密hashlib

用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import hashlib

# ######## md5 ########
hash = hashlib.md5()
# help(hash.update)
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())
print(hash.digest())


######## sha1 ########

hash = hashlib.sha1()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())

# ######## sha256 ########

hash = hashlib.sha256()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())


# ######## sha384 ########

hash = hashlib.sha384()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())

# ######## sha512 ########

hash = hashlib.sha512()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())

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

1
2
3
4
5
6
7
import hashlib

# ######## md5 ########

hash = hashlib.md5(bytes('898oaFs09f',encoding="utf-8"))
hash.update(bytes('admin',encoding="utf-8"))
print(hash.hexdigest())

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

1
2
3
4
5
import hmac

h = hmac.new(bytes('898oaFs09f',encoding="utf-8"))
h.update(bytes('admin',encoding="utf-8"))
print(h.hexdigest())
8. requests

Requests 是使用 Apache2 Licensed 许可证的 基于Python开发的HTTP 库,其在Python内置模块的基础上进行了高度的封装,从而使得进行网络请求时,变得美好了许多,因为使用Requests可以轻而易举的完成浏览器可有的任何操作

1)安装模块

pip3 install requests

2) 使用模块

  • get请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 1、无参数实例

import requests
ret = requests.get('https://github.com/timeline.json')

print(ret.url)
print(ret.text)


# 2、有参数实例
import requests

payload = {'key1': 'value1', 'key2': 'value2'}
ret = requests.get("http://httpbin.org/get", params=payload)

print(ret.url)
print(ret.text)
  • post请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1、基本POST实例

import requests

payload = {'key1': 'value1', 'key2': 'value2'}
ret = requests.post("http://httpbin.org/post", data=payload)

print(ret.text)


# 2、发送请求头和数据实例

import requests
import json

url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
headers = {'content-type': 'application/json'}

ret = requests.post(url, data=json.dumps(payload), headers=headers)

print(ret.text)
print(ret.cookies)
  • 其他请求
1
2
3
4
5
6
7
8
9
10
requests.get(url, params=None, **kwargs)
requests.post(url, data=None, json=None, **kwargs)
requests.put(url, data=None, **kwargs)
requests.head(url, **kwargs)
requests.delete(url, **kwargs)
requests.patch(url, data=None, **kwargs)
requests.options(url, **kwargs)

# 以上方法均是在此方法的基础上构建
requests.request(method, url, **kwargs)
9. subprocess

这个模块主要是用来替换os.system()以及os.spawn()

subprocess包主要功能是执行外部的命令和程序。比如说,我需要使用wget下载文件。我在Python中调用wget程序。从这个意义上来说,subprocess的功能与shell类似

  • 常见的subprocess的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import subprocess

#执行命令,如果命令结果为0,就正常返回,否则抛异常
>>> res = subprocess.call(["ls", "-l"])

#执行命令,如果命令结果为0,就正常返回,否则抛异常
>>> res = subprocess.check_call(["ls", "-l"])

#执行命令,并返回结果,注意是返回结果,不是打印,下例结果返回给res
>>> res=subprocess.check_output(['ls','-l'])
>>> res
b'total 0\ndrwxr-xr-x 12 shangzekai staff 402 Nov 3 12:25 dd.txt\n'

#通过一个shell来解释一整个字符串
out = subprocess.call("ls -l", shell=True)
out = subprocess.call("cd ..", shell=True)

#我们使用了shell=True这个参数。这个时候,我们使用一整个字符串,而不是一个表来运行。Python将先运行一个shell,再用这个shell来解释这整个字符串

以上的那些方法,我们底层调用的都是Popen() 方法

1
2
3
>>> p = subprocess.Popen("df -h|grep disk",stdin=subprocess.PIPE,stdout=subprocess.PIPE,shell=True)
>>> p.stdout.read()
b'/dev/disk1 465Gi 64Gi 400Gi 14% 16901472 104938142 14% /\n'
  • stdin 标准输入

  • stdout 标准输出

  • stderr 标准错误

除了上述的一些方法之外,强烈推荐调用另一种方法,subprocess.run(…)

1
2
p = subprocess.Popen("find / -size +1000000 -exec ls -shl {} \;",shell=True,stdout=subprocess.PIPE)
print(p.stdout.read())

可用参数

1
2
3
4
5
6
7
8
9
10
11
12
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()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等

subprocess实现sudo 自动输入密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import subprocess

def mypass():
mypass = '123' #or get the password from anywhere
return mypass

echo = subprocess.Popen(['echo',mypass()],
stdout=subprocess.PIPE,
)

sudo = subprocess.Popen(['sudo','-S','iptables','-L'],
stdin=echo.stdout,
stdout=subprocess.PIPE,
)

end_of_pipe = sudo.stdout

print("Password ok \n Iptables Chains %s" % end_of_pipe.read())
10. 正则表达式

常见的正则表达式符号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
'.'     默认匹配除\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'}

常见的使用方法

  • re.match 从头开始匹配

    match(pattern, string, flags=0)
    pattern: 正则模型
    string : 要匹配的字符串
    falgs : 匹配模式

    • re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
    • M(MULTILINE): 多行模式,改变’^’和’$’的行为
    • S(DOTALL): 点任意匹配模式,改变’.’的行为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 无分组
r = re.match("h\w+", origin)
print(r.group()) # 获取匹配到的所有结果
print(r.groups()) # 获取模型中匹配到的分组结果
print(r.groupdict()) # 获取模型中匹配到的分组结果

# 有分组

# 为何要有分组?提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来)

r = re.match("h(\w+).*(?P<name>\d)$", origin)
print(r.group()) # 获取匹配到的所有结果
print(r.groups()) # 获取模型中匹配到的分组结果
print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组
  • re.search 浏览整个字符串去匹配第一个,未匹配成功返回None

    search(pattern, string, flags=0)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 无分组
    r = re.search("a\w+", origin)
    print(r.group()) # 获取匹配到的所有结果
    print(r.groups()) # 获取模型中匹配到的分组结果
    print(r.groupdict()) # 获取模型中匹配到的分组结果

    # 有分组
    r = re.search("a(\w+).*(?P<name>\d)$", origin)
    print(r.group()) # 获取匹配到的所有结果
    print(r.groups()) # 获取模型中匹配到的分组结果
    print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组
  • re.findall 把所有匹配到的字符放到列表中,以列表中的元素返回

    findall(pattern, string, flags=0)

    1
    2
    3
    4
    5
    6
    7
    8
    # 无分组
    r = re.findall("a\w+",origin)
    print(r)

    # 有分组
    origin = "hello alex bcd abcd lge acd 19"
    r = re.findall("a((\w*)c)(d)", origin)
    print(r)
  • re.split 以匹配到的字符当做列表分隔符

    split(pattern, string, maxsplit=0, flags=0)
    pattern: 正则模型
    string : 要匹配的字符串
    maxsplit:指定分割个数
    flags : 匹配模式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 无分组
    origin = "hello alex bcd alex lge alex acd 19"
    r = re.split("alex", origin, 1)
    print(r)

    # 有分组

    origin = "hello alex bcd alex lge alex acd 19"
    r1 = re.split("(alex)", origin, 1)
    print(r1)
    r2 = re.split("(al(ex))", origin, 1)
    print(r2)
  • re.sub 匹配字符并替换

    sub(pattern, repl, string, count=0, flags=0)
    pattern: 正则模型
    repl : 要替换的字符串或可执行对象
    string : 要匹配的字符串
    count : 指定匹配个数
    flags : 匹配模式

1
2
3
origin = "hello alex bcd alex lge alex acd 19"
r = re.sub("a\w+", "999", origin, 2)
print(r)

常见的正则表达式

IP:
^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$
手机号:
^1[3|4|5|8][0-9]\d{8}$
邮箱:
[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+