前言:python中有众多的模块,下面我列举几个常用的模块。

第一:time模块

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

时间戳               1970年1月1日之后的秒,运行“type(time.time())”,返回的是float类型。即:time.time()

格式化的字符串    2014-11-11 11:11,即:time.strftime('%Y-%m-%d')

结构化时间          struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)  即:time.localtime()

认识时间的形式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import time
 
#首先认识三种形式的时间
print(time.time()
1492355202.6346803
 
#格式化的时间字符串:
print(time.strftime("%Y-%m-%d %X"))
#2017-04-16 23:06:42
 
#本地时区的struct_time
print(time.localtime())
#time.struct_time(tm_year=2017, tm_mon=4, tm_mday=16, tm_hour=23, tm_min=6, tm_sec=42, tm_wday=6, tm_yday=106, tm_isdst=0)
 
#UTC时区的struct_time
print(time.gmtime())
 
#time.struct_time(tm_year=2017, tm_mon=4, tm_mday=16, tm_hour=15, tm_min=6, tm_sec=42, tm_wday=6, tm_yday=106, tm_isdst=0)

时间之间的转换:

num1:

1
2
3
4
5
6
7
8
9
10
11
#时间戳转为结构化的时间
import time
print(time.localtime())
print(time.gmtime())
print(time.localtime(1483588666))
print(time.gmtime(1483588666))
 
# time.struct_time(tm_year=2017, tm_mon=4, tm_mday=17, tm_hour=16, tm_min=53, tm_sec=27, tm_wday=0, tm_yday=107, tm_isdst=0)
# time.struct_time(tm_year=2017, tm_mon=4, tm_mday=17, tm_hour=8, tm_min=53, tm_sec=27, tm_wday=0, tm_yday=107, tm_isdst=0)
# time.struct_time(tm_year=2017, tm_mon=1, tm_mday=5, tm_hour=11, tm_min=57, tm_sec=46, tm_wday=3, tm_yday=5, tm_isdst=0)
# time.struct_time(tm_year=2017, tm_mon=1, tm_mday=5, tm_hour=3, tm_min=57, tm_sec=46, tm_wday=3, tm_yday=5, tm_isdst=0)

num2: 

1
2
3
#结构化的时间转换为时间戳
print(time.mktime(time.localtime()))
#1492419465.0

num3:

1
2
3
#结构化的时间转换为格式化的字符串时间
print(time.strftime("%Y-%m-%d %X", time.localtime()))
#2017-04-17 17:06:23

num4:

1
2
3
#格式化的字符串时间转换为结构化的时间
print(time.strptime('2017-04-17 17:05:06','%Y-%m-%d %X'))
#time.struct_time(tm_year=2017, tm_mon=4, tm_mday=17, tm_hour=17, tm_min=5, tm_sec=6, tm_wday=0, tm_yday=107, tm_isdst=-1)

第二:os模块

 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('dirname1/dirname2')    可生成多层递归目录
os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove()  删除一个文件
os.rename("oldname","newname")  重命名文件/目录
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所指向的文件或者目录的最后修改时间

os 路径处理:

复制代码
os路径处理
#方式一:
import os
#具体应用,openstack源码中的使用方式
import os,sys
possible_topdir = os.path.normpath(os.path.join(
    os.path.abspath(__file__),
    os.pardir, #上一级
    os.pardir,
    os.pardir
))
sys.path.insert(0,possible_topdir)


#方式二:django中的使用方式
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
复制代码

第三: sys模块

sys:与python解释器进行交互

复制代码
sys.argv           命令行参数List,第一个元素是程序本身路径,开发监控程序的时候会进程用到的
sys.exit(n)        退出程序,正常退出时exit(0)
sys.version        获取Python解释程序的版本信息
sys.maxint         最大的Int值
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操作系统平台名称
复制代码

第四: logging模块

复制代码
#输出到屏幕
import logging

logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
#输出
# WARNING:root:warning message
# ERROR:root:error message
# CRITICAL:root:critical message
复制代码

综上:

可见,默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET),默认的日志格式为日志级别:Logger名称:用户输出消息。
复制代码
#打印到文件
import sys
import os
project_path = os.path.dirname(os.path.abspath(__file__))
sys.path.append(project_path)

import logging
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S',
                    filename='%s/log/log.txt'% project_path,
                    filemode='w')

logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
复制代码

第五: random模块

复制代码
import random

print(random.random())#(0,1)----float    大于0且小于1之间的小数

print(random.randint(1,5))  #[1,5]    大于等于1且小于等于5之间的整数

print(random.randrange(1,5)) #[1,5)    大于等于1且小于5之间的整数

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)
复制代码
 生成随机验证码

第六:json&&pickle模块

首先要知道什么是序列化?

  我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。

其次要明白为什么要有序列化?

  1:持久保存状态

    将状态保存在硬盘中

  2:跨平台数据交互

    序列化之后,不仅可以把序列化后的内容写入磁盘,还可以通过网络传输到别的机器上,如果收发的双方约定好实用一种序列化的格式,那么便打破了平台/语言差异化带来的限制,实现了跨平台数据交互

json介绍:

  如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。

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

  常用的是dumps和loads,针对文件的操作

复制代码
import json
dic = {'name':'zzl','age':'18','sex':'male'}
j=json.dumps(dic)
f=open('test.txt','w')
f.write(j)
f.close()

f=open('test.txt','r')
data=json.loads(f.read())
print(data)
{'sex': 'male', 'age': '18', 'name': 'zzl'}
复制代码

pickle:

  Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系

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

    同样pickle常用的也是dumps和loads,针对文件的操作

复制代码
import pickle

dic = {'name':'zzl','age':'18','sex':'male'}
j=pickle.dumps(dic)
print(type(j)) #<class 'bytes'>
f=open('pickle','wb')#由于j的类型是bytes,所以必须写入bytes,需要用wb的方式
f.write(j)
f.close()

#反序列化
f=open('pickle','rb')
data=pickle.loads(f.read())
f.close()
print(data)
#{'age': '18', 'name': 'zzl', 'sex': 'male'}
复制代码

第七:shutil模块

  shutil模块是高级的 文件、文件夹、压缩包 处理模块。

复制代码
import shutil

#shutil.copyfileobj(fsrc, fdst[, length]) 拷贝文件内容
shutil.copyfileobj(open('test.txt','r'),open('test2.txt','w'))

# shutil.copyfile(src, dst)  拷贝文件
shutil.copyfile('log.txt','log2.txt')

# shutil.copymode(src, dst) 仅拷贝权限。内容、组、用户均不变
shutil.copymode('test.txt', 'log.txt') #目标文件必须存在

# shutil.copystat(src, dst)  仅拷贝状态的信息,包括:mode bits, atime, mtime, flags
shutil.copystat('test.txt', 'test2.txt') #目标文件必须存在

# shutil.copy(src, dst) 拷贝文件和权限
shutil.copy('test.txt', 'test2.txt')

#shutil.copy2(src, dst)  拷贝文件和状态信息
shutil.copy2('test.txt', 'test2.txt')

# 递归的去拷贝文件夹
# shutil.ignore_patterns(*patterns)
# shutil.copytree(src, dst, symlinks=False, ignore=None)
shutil.copytree('log', 'folder', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除
shutil.copytree('log', 't2', symlinks=True, ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))#拷贝软连接文件,并且忽略已pyc和tmp结尾的

#shutil.rmtree(path[, ignore_errors[, onerror]])#递归的去删除文件
shutil.rmtree('folder2')

# shutil.move(src, dst) 类似于mv命令,就是重命名
shutil.move('folder', '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 两个模块来进行的,详细介绍:

复制代码
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()
复制代码
复制代码
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()
复制代码

第八:shelve模块

shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型。
先上一个错误示例(潜在的小问题)
复制代码
import shelve

f=shelve.open(r'sheve.txt')
f['x']=['a','b','c']
f['x'].append('d')
print(f['x'])
f.close()

#输出结果:
['a', 'b', 'c']
复制代码

d 跑那里去了?其实很简单,d没有写回,你把['a', 'b', 'c']存到了x,当你再次读取s['x']的时候,s['x']只是一个拷贝,而你没有将拷贝写回,所以当你再次读取s['x']的时候,它又从源中读取了一个拷贝,所以,你新修改的内容并不会出现在拷贝中,解决的办法就是,第一个是利用一个缓存的变量,如下所示

复制代码
import shelve

f=shelve.open(r'sheve.txt')
f['x']=['a','b','c']
tmp=f['x']
tmp.append('d')
f['x']=tmp
print(f['x'])
f.close()

#输出结果:
['a', 'b', 'c', 'd']
复制代码

第九:configparser

软件的格式好多是以ini结尾的

复制代码
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes

[bitbucket.org]
User = hg

[topsecret.server.com]
Port = 50022
ForwardX11 = no
复制代码

1.获取所有的节点:(注意DEFAULT默认的是获取不到的)

复制代码
import configparser
config=configparser.ConfigParser()
config.read('test.ini',encoding='utf-8')
res=config.sections()
print(res)

输出结果:
['bitbucket.org', 'topsecret.server.com']
复制代码

2 获取指定节点下所有的键值对(会获取default的节点下的键值对和指定节点下的键值对,如果默认的键值对与指定节点下的键值对重复,则获取到的是指定节点下的键值对)

复制代码
import configparser
config=configparser.ConfigParser()
config.read('test.ini',encoding='utf-8')
res=config.items('topsecret.server.com')
print(res)

输出结果:
[('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardx11', 'no'), ('port', '50022')]
复制代码

3.获取指定节点下的所有键

复制代码
import configparser
config=configparser.ConfigParser()
config.read('test.ini',encoding='utf-8')
res=config.options('bitbucket.org')
print(res)
输出结果:
['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardx11']
复制代码

4. 获取指定节点下指定key的值

复制代码
import configparser
config=configparser.ConfigParser()
config.read('test.ini',encoding='utf-8')

res1=config.get('bitbucket.org','user')
res2=config.getint('topsecret.server.com','port')
res3=config.getfloat('topsecret.server.com','port')
res4=config.getboolean('topsecret.server.com','ForwardX11')

print(res1)
print(res2)
print(res3)
print(res4)
输出:
hg
50022
50022.0
False
复制代码

5.检测节点是否存在,添加节点,删除节点。

复制代码
import configparser
config=configparser.ConfigParser()
config.read('test.ini',encoding='utf-8')

#检查
has_sec=config.has_section('bitbucket.org')
print(has_sec) #打印True,不存在则报错

#添加节点
config.add_section('zzl') #已经存在则报错
config['zzl']['username']='zhanling'
config['zzl']['age']='18'
config.write(open('test.ini','w'))

# #删除节点
config.remove_section('zzl')
config.write(open('test.ini','w'))
复制代码

6.检查、删除、设置指定组内的键值对

复制代码
import configparser
config=configparser.ConfigParser()
config.read('test.ini',encoding='utf-8')

#检查
has_sec=config.has_option('bitbucket.org','user') #bitbucket.org下有一个键user
print(has_sec) #打印True

#删除
config.remove_option('DEFAULT','forwardx11') #删除DEFAULT节点下的forwardx11
config.write(open('test.ini','w')) #加载配置

#设置
config.set('zzl','username','zhangzhanling') #更改zzl节点下的username为zhangzhanling
config.write(open('test.ini','w'))
复制代码

7.新建一个ini的文件

复制代码
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)
复制代码

第十: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('utf8'))
print(m.hexdigest())  #5d41402abc4b2a76b9719d911017c592
 
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('898oaFsds09f'.encode('utf8'))
hash.update('alvin'.encode('utf8'))
print (hash.hexdigest())#e79e68f070cdedcfe63eaf1a2e92c83b4cfb1b5c6bc452d214c1b7e77cdfd1c7
复制代码

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

import hmac
h = hmac.new('alvin'.encode('utf8'))
h.update('hello'.encode('utf8'))
print (h.hexdigest())#320df9832eab4c038b6c1d7ed73a5940

第十一:re正则

  正则表达式(或 RE)是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。

  字符匹配(普通字符,元字符):

1 普通字符:大多数字符和字母都会和自身匹配
              >>> re.findall('alvin','yuanaleSxalexwupeiqi')
                      ['alvin'] 

2 元字符:. ^ $ * + ? { } [ ] | ( ) \

复制代码
import re

ret=re.findall('a..in','hellosahaelin')
print(ret)
# 解释:. 匹配一个字符
# 输出结果:
# ['ahelin']

ret=re.findall('^a...n','aeeenadhfajkdh')
print(ret)
# 解释:  ^ 匹配开头
# 输出结果:
# ['aeeen']


ret=re.findall('a..v$','aasdfdassv')
print(ret)
# 解释: $ :匹配结危
# 输出结果:
# ['assv']

ret=re.findall('abc*','abccc')
print(ret)

#贪婪匹配
# 输出结果:
#['abcccc']


ret=re.findall('abc?','abcddcc')
print(ret)
# 解释:?:? 问号代表前面的字符最多只可以出现一次(0次、或1次)
# 输出结果:
#['abc']

ret=re.findall('abc{1,4}','abcccccc')
print(ret)
# 解释:{1,4}最多匹配4个
# 输出结果:
#['abcccc'] 贪婪匹配
复制代码

元字符之字符集[]:

复制代码
#----------字符集[]
ret=re.findall('a[bc]d','acd')
print(ret)
#['acd']

ret=re.findall('[a-z]','acd')
print(ret)
#['a', 'c', 'd']

ret=re.findall('[.*+]','a.cd+')
print(ret)
#['.', '+']

#在字符集里有功能的符号: - ^ \

ret=re.findall('[1-9]','45dha3')
print(ret)
#['4', '5', '3']

ret=re.findall('[^ab]','45bdha3')
print(ret)
#['4', '5', 'd', 'h', '3']

ret=re.findall('[\d]','45bdha3')
print(ret)
#['4', '5', '3']
复制代码

元字符之转义符\

反斜杠后边跟元字符去除特殊功能,比如\.
反斜杠后边跟普通字符实现特殊功能,比如\d

\d  匹配任何十进制数;它相当于类 [0-9]。
\D 匹配任何非数字字符;它相当于类 [^0-9]。
\s  匹配任何空白字符;它相当于类 [ \t\n\r\f\v]。
\S 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]。
\w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
\W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]
\b  匹配一个特殊字符边界,比如空格 ,&,#等

ret=re.findall('I\b','I am LIST')
print(ret)#[]
ret=re.findall(r'I\b','I am LIST')
print(ret)#['I']

元字符之分组()

复制代码
m = re.findall(r'(ad)+', 'add')
print(m)
 
ret=re.search('(?P<id>\d{2})/(?P<name>\w{3})','23/com')
print(ret.group())#23/com
print(ret.group('id'))#23
复制代码

元字符之|

ret=re.search('(ab)|\d','rabhdg8sd')
print(ret.group())#ab

re模块下的常用方法

复制代码
import re

ret=re.findall('a','alvin yuan')
print(ret)
#解释:返回所有满足匹配条件的结果,放在列表里
# 输出结果:
# ['a', 'a']

ret=re.search('a','alvin yuan').group()
print(ret)
#解释:函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
                                     # 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
# 输出结果:
# a

ret=re.match('a','abc').group()
print(ret)
#解释: 同search,不过是在字符串开始处进行匹配
# 输出结果:
# a


ret=re.split('[ab]','abcd')
print(ret)
#解释:先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
# 输出结果:
#['', '', 'cd']


ret=re.sub('\d','abc','alvin5yuan6',1)
print(ret)

# 解释:把第一个数字替换成abc
# 输出结果:
#alvinabcyuan6

ret=re.subn('\d','abc','alvin5yuan6sss7')
print(ret)
# 解释:里面有几个字符就替换成几个abc
# 输出结果:
# ('alvinabcyuanabcsssabc', 3)



obj=re.compile('\d{3}')
ret=obj.search('abc123eeee')
print(ret.group())
# 解释:匹配三个数字在一起的
# 输出结果:
# abc
复制代码

第十二:paramiko模块