re模块(正则模块)

正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法。或者说:正则就是用来描述一类事物的规则。(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。

\w        匹配字母数字及下划线

\W       匹配非字母数字下划线

\s         匹配任意空白字符,等价于【\t\n\r\f

\S        匹配任意非空字符

\d        匹配任意数字,等价于【0-9

\D        匹配任意非数字

\A        匹配字符串

\Z        匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串

\z         匹配字符串结束

\G        匹配最后匹配完成的位置

\n        匹配一个换行符

\t         匹配一个制表符

^         匹配字符串的开头

$          匹配字符串的末尾

.          匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符

[…]      用来表示一组字符,单独列出:【amk】匹配’a’’m’或‘k

[^…]          不在[]中的字符

*          匹配0个或多个的表达式

+         匹配1个或多个的表达式

?          匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式

{n}       精确匹配n个前面表达式

{n,m}         匹配nm次由前面的正则表达式定义的片段,贪婪方式

a|b       匹配ab

()         匹配括号内的表达式,也表示一个组

 

import re
print(re.findall('\w','hello_ | egon 123'))
print(re.findall('\W','hello_ | egon 123'))
print(re.findall('\s','hello_ | egon 123 \n \t'))
print(re.findall('\S','hello_ | egon 123 \n \t'))
print(re.findall('\d','hello_ | egon 123 \n \t'))
print(re.findall('\D','hello_ | egon 123 \n \t'))
print(re.findall('h','hello_ | hello h egon 123 \n \t'))
print(re.findall('\Ahe','hello_ | hello h egon 123 \n \t'))
print(re.findall('^he','hello_ | hello h egon 123 \n \t'))
print(re.findall('123\Z','hello_ | hello h egon 123 \n \t123'))
print(re.findall('123$','hello_ | hello h egon 123 \n \t123'))
print(re.findall('\n','hello_ | hello h egon 123 \n \t123'))
print(re.findall('\t','hello_ | hello h egon 123 \n \t123'))

输出:
['h', 'e', 'l', 'l', 'o', '_', 'e', 'g', 'o', 'n', '1', '2', '3']
[' ', '|', ' ', ' ']
[' ', ' ', ' ', ' ', '\n', ' ', '\t']
['h', 'e', 'l', 'l', 'o', '_', '|', 'e', 'g', 'o', 'n', '1', '2', '3']
['1', '2', '3']
['h', 'e', 'l', 'l', 'o', '_', ' ', '|', ' ', 'e', 'g', 'o', 'n', ' ', ' ', '\n', ' ', '\t']
['h', 'h', 'h']
['he']
['he']
['123']
['123']
['\n']
['\t']


re模块提供的方法:

  re.findall()    查找所有满足匹配条件的结果,放在列表中

re.search()             只找到第一个匹配到的然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None
re.match()              同search,不过在字符串开始出进行匹配,完全可以使用search+^代替match
re.split()                 按匹配内容对对象进行分割
re.sub()                  替换,(老的值,新的值,替换对象,替换次数),不指定替换次数,默认替换所有
re.subn()                同sub,不过结果中返回替换的次数
re.compile             重用匹配格式

 

 

 

 

3time模块

Python中,通常有以下三种方式来计算时间:

a.时间戳:

时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型

 

b.格式化的时间字符串

c.结构化的时间

struct_time元组共有9个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)

 

4random模块

 

5os模块

 

6sys模块

 

7jsonpickle模块(序列化模块)

把对象(变量)从内存中变成可存储或传输的过程称为序列化


Python中叫pickling,在其他语言中也被称之为serializationmarshallingflattening等等

序列化的作用:

a.持久保存状态

在断电或重启程序之前将程序当前内存中所有的数据都保存下来(保存到文件中),以便于下次程序执行能够从文件中载入之前的数据,然后继续执行,这就是序列化


b.跨平台数据交互

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


json模块

如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便,所以json适合数据跨平台交互时使用(但是跨平台意味着不会支持某种语言的所有数据类型,如不支持python函数的序列化)


内存中结构化的数据<---> 格式json <--->字符串 <---> 保存到文件中或基于网络传输


使用:

dump         序列化

load           反序列化

import json
dic={'name':'egon','age':18}
with open('a.json','w') as f: # 序列化字典到文件内容
    f.write(json.dumps(dic)) 
with open('a.json','r') as f: # 反序列化输出
    data=f.read()
    dic=json.loads(data)

 

dumps        序列化

loads          反序列化

import json
dic={'name':'egon','age':18}
json.dump(dic,open('b.json','w'))     # 序列化字典到文件内容
print(json.load(open('b.json','r'))['name'])  # 反序列化输出

 

pickle模块

pickle只能用于Python(所有数据类型),并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。


内存中结构化的数据<---> 格式pickl<---> bytes类型 <---> 保存到文件中或基于网络传输

dumps             序列化

loads          反序列化

dump             序列化

load           反序列化

import pickle
dic={'name':'egon','age':18}
with open('d.pkl','wb') as f:        # 序列化字典到文件内容
    f.write(pickle.dumps(dic)) 
with open('d.pkl','rb') as f:        # 反序列化输出
    dic=pickle.loads(f.read())         
    print(dic['name'])
import pickle
dic={'name':'egon','age':18}
pickle.dump(dic,open('e.pkl','wb'))   # 序列化字典到文件内容
print(pickle.load(open('e.pkl','rb'))['name']) # 反序列化输出

pickle是根据内存地址进行反序列化的,所以该内存地址对应的数据在命名空间中必须是已定义的


8shelve模块


9、shutil模块

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


常用方法:


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

shutil.copyfileobj(源文件, 目标文件[, length])

 

拷贝文件:

shutil.copyfile(src, dst)   # 目标文件无需存在

 

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

shutil.copymode(src, dst)   # 目标文件必须存在


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

shutil.copystat(src, dst)     #目标文件必须存在

 

拷贝文件和权限

shutil.copy(src, dst) 


拷贝文件和状态信息

shutil.copy2(src, dst) 


递归的去拷贝文件夹

shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)  #目标目录不能存在,注意对dst目录父级目录要有可写权限,ignore的意思是排除 

 

拷贝软连接

import shutil

shutil.copytree('f1', 'f2', symlinks=True,ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))

通常的拷贝都把软连接拷贝成硬链接,即对待软连接来说,创建新的文件



递归的去删除文件

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

 

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

shutil.move(src, dst)

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

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

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()


10、xml模块

xml是实现不同语言或程序之间进行数据交换的协议,跟json功能差不多,但json使用起来更简单,由于比json出现的早,至今很多传统公司如金融行业的很多系统的接口还主要是xml

xml是通过<>节点(标签)来区别数据结构的

<?xml version="1.0"?>
<data>
   <country name="Liechtenstein">
       <rank updated="yes">2</rank>
       <year>2008</year>
       <gdppc>141100</gdppc>
       <neighbor name="Austria" direction="E"/>
       <neighbor name="Switzerland" direction="W"/>
   </country>
   <country name="Singapore">
       <rank updated="yes">5</rank>
       <year>2011</year>
       <gdppc>59900</gdppc>
       <neighbor name="Malaysia" direction="N"/>
   </country>
   <country name="Panama">
       <rank updated="yes">69</rank>
       <year>2011</year>
       <gdppc>13600</gdppc>
       <neighbor name="Costa Rica" direction="W"/>
       <neighbor name="Colombia" direction="E"/>
   </country>
</data>


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,child.attrib['name'])
    fori 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')

#删除node
for country in root.findall('country'):
  rank = int(country.find('rank').text)
   ifrank > 50:
    root.remove(country)
 
tree.write('output.xml')


11、configparser模块

主要用来解析配置文件

配置文件为以下格式:

[section1]

k1 = v1

k2:v2

user=egon

age=18

is_admin=true

salary=31


[section2]

k1 = v1

 

操作方法如下:

import configparser                     #  导入模块

config=configparser.ConfigParser()       #使用ConfigParser方法得到一个对象赋值给config

 

查看标题:

config.sections()

 

查看标题section1下所有key=valuekey

config.options('section1')

 

查看标题section1下所有key=value(key,value)格式

config.items('section1')

 

查看标题section1user的值,字符串格式

config.get('section1','user')

 

查看标题section1age的值,整数格式

val1=config.getint('section1','age')

 

查看标题section1is_admin的值,布尔值格式

config.getboolean('section1','is_admin')

 

查看标题section1salary的值,浮点型格式

config.getfloat('section1','salary')

 

删除整个标题section2

config.remove_section('section2')

 

删除标题section1下的某个k1k2

config.remove_option('section1','k1')

config.remove_option('section1','k2')

 

判断是否存在某个标题

config.has_section('section1')

 

判断标题section1下是否有user

config.has_option('section1','user')

 

添加一个标题

config.add_section('egon')

 

在标题egon下添加name=egon,age=18的配置

config.set('egon','name','egon')

config.set('egon','age',18)    #报错,必须是字符串

 

最后将修改的内容写入文件,完成最终的修改

config.write(open('a.cfg','w'))

 

12、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('898oaFs09f'.encode('utf8'))
hash.update('alvin'.encode('utf8'))
print (hash.hexdigest())#e79e68f070cdedcfe63eaf1a2e92c83b4cfb1b5c6bc452d214c1b7e77cdfd1c7
 
 
import hashlib
passwds=[
    'alex3714',
    'alex1313',
    'alex94139413',
    'alex123456',
    '123456alex',
    'a123lex',
    ]
def make_passwd_dic(passwds):
    dic={}
    for passwd inpasswds:
        m=hashlib.md5()
       m.update(passwd.encode('utf-8'))
       dic[passwd]=m.hexdigest()
    return dic
 
def break_code(cryptograph,passwd_dic):
    for k,v inpasswd_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('alvin'.encode('utf8'))
h.update('hello'.encode('utf8'))
print (h.hexdigest())#320df9832eab4c038b6c1d7ed73a5940

#要想保证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())
 
h2=hmac.new(b'egon')
h2.update(b'helloworld')
print(h2.hexdigest())
 
h3=hmac.new(b'egonhelloworld')
print(h3.hexdigest())
 
'''
f1bf38d054691688f89dcd34ac3c27f2
f1bf38d054691688f89dcd34ac3c27f2
bcca84edd9eeb86f30539922b28f3981
'''

 

5.subprocess模块

python解释器中开启一个子进程执行shell命令

stdout           标准正确输出      # 输出内容为bytes类型,如果在windows输出需要解码为decode(‘gbk’),linux解码为decode(‘utf-8’)

stderr          标准错误输出

stdin         标准输入

shell=True       使用shell命令

subprocess.PIPE    把输出结果放到管道

 

res1=subprocess.Popen('ls/Users/jieli/Desktop',shell=True,stdout=subprocess.PIPE)

# 先列出桌面上的文件

subprocess.Popen('grep txt$',shell=True,stdin=res1.stdout,stdout=subprocess.PIPE)

# 把上面的数据交给这条命令作为输入结果,过滤以txt结尾的文件