九.python基础模块

1.模块

1.1 模块的概念

  • 学习模块之前回顾下,我们为什么要学习函数呢? 之前我们写代码用的是基本的赋值以及条件及循环语句,来控制代码的逻辑,后来代码写的太多,可读性比较差 这个时候,我们用函数把特定的功能封装起来,使代码可读性变得更好,但是,函数都是在一个文件中存在的, 如果要写更大的程序,都放在一个文件中,这个时候可读性又变得很差,怎么办呢?
    这个时候为了解决代码的可读性以及维护性,我们把一类的功能分别放到不同的文件中,这样每个文件中的代码 就相对较少,大大提高了代码的可维护性,以及可读性。(不仅仅是python这样,很多语言都采用这种方式)

  • 定义:在python中,一个.py 的文件就称之为一个模块。

  • 使用模块的好处

  1. 提高代码的可维护性
  2. 提高代码的可读性。
  3. 可以直接引用(比如我们用一个时间的模块,直接import time就可以了,不用自己写time的功能)
  4. 可以避免函数名冲突,相同名字的函数和变量可以在不同模块中存在,我们不需要考虑函数名冲突。(但是需要注意,内置函数也可能是一个模块,所以我们的模块名,尽量不要与内置函数名冲突)
  • 模块的分类(在python中模块一共分为3类)

  1. python标准库
  2. 第三方模块
  3. 自定义模块
  • 模块的导入方法
  1. import语句
  2. from...import... 语句
  3. from...import *  语句

  注意:导入 * 是不好的,因为它常常产生难以阅读的代码,并且会容易产生名字冲突。(因为很多文件中可能有相同的函数,导致冲突)

 1.2 模块库存放位置

 1 C:\Users\Administrator>python
 2 Python 3.6.2 (v3.6.2:5fd33b5, Jul  8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)]
 3  on win32
 4 Type "help", "copyright", "credits" or "license" for more information.
 5 >>> import sys
 6 >>> for i in sys.path:
 7 ...     print(i)
 8 ...
 9 
10 C:\python36\python36.zip
11 C:\python36\DLLs
12 C:\python36\lib                    #标准库        
13 C:\python36
14 C:\python36\lib\site-packages      #第三方模块
15 >>>    

1.3 模块的导入方法

  以上介绍模块导入的三种方法,这里用示例来演示模块的使用

  示例文件如下文件名为test.py模块名为test

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 
 4 print('from the test.py')
 5 
 6 num = 10
 7 
 8 def func1():
 9     print('test->func1->num',num)
10 
11 def func2():
12     print('test->func2')
13     func1()
14 
15 def func3():
16     global num
17     num=20
  • import语句使用
 1 #导入示例
 2 >>> import test    #第一次导入是加载到内存,再次导入相同模块会在内存中多一次引用计数
 3 from the test.py    #test模块中的顶级代码会在导入的时候就执行
 4 >>>
 5 
 6 #全局变量不冲突
 7 
 8 >>> import test
 9 from the test.py
10 >>> num = 20
11 >>> print(num)
12 20
13 >>> print(test.num)
14 10
15 >>> 
16 
17 #函数不冲突
18 
19 >>> import test
20 from the test.py
21 >>> num = 20
22 >>> def func1():
23 ...     print('func1->num',num)            
24 ... 
25 >>> func1()
26 func1->num 20
27 >>> test.func1()
28 test->func1->num 10
29 >>> 
30 
31 #全局变量不冲突
32 
33 >>> import test
34 from the test.py
35 >>> num = 20
36 >>> test.func3()
37 >>> print(num)
38 20
39 >>> 
import使用

  当有相同种类的模块,导入的时候我们可以起别名

 1 #例如test模块有以下两个函数
 2 def func1():
 3     print("func1")
 4 
 5 def func2():
 6     print("func2")
 7 
 8 #别名导入方法
 9 
10 import func1 as test1
11 import func2 as test2
12 
13 #好处是模块较多的时候我们可以自定义别名进行区分
  • from...import... 语句使用

  import导入是导入整个模块,在使用的时候我们必须用(模块名.函数名来获取),当我们要获取单一方法的时候可以用from...import...的方式

 1 #结合以上示例
 2 
 3 >>> from test import func1
 4 >>> func1()     #这里可以直接调用而非test.func1()来调用
 5 test->func1->num 20
 6 >>> 
 7 
 8 #导入func1函数,执行的时候会回到test中寻找变量
 9 
10 >>> from test import func1
11 from the test.py
12 >>> func1()
13 test->func1->num 10
14 >>> 
15 
16 #导入func2函数,执行时候调用func1也会回到test中的func1寻找
17 
18 >>> from test import func2
19 from the test.py
20 >>> func2()
21 spam->func2
22 test->func1->num 10
23 >>> 
24 
25 #导入func1函数,在本作用域又创建同名函数,这时候会覆盖
26 
27 >>> from test import func1
28 >>> func1()
29 test->func1->num 20
30 >>> 
31 >>> 
32 >>> def func1():
33 ...     print("func1")
34 ... 
35 >>> func1()
36 func1
37 >>> 
from...import... 语句使用示例
  • from...import *  语句使用

   这种方法不建议使用,因为模块中会有相同的函数,这样后导入的就会覆盖先导入的,导致问题的出现。

  from...import * 不会导入以_开头的变量或函数。

  可以用__all__来控制*号

  比如:__all__['func1','func2'] ,这样使用from test import *的时候,只会导入func1和func2这两个方法。

 1.4 模块的搜索路径

  模块加载的先后顺序

  1. 内存中加载的模块
    python解释器在启动时会自动加载一些模块,可以使用sys.modules查看
  2. 内置模块
    比如sys模块,在python的环境变量下找不到
  3. sys.path路径中的模块(sys.pathsys.path路径位置寻找顺序:1.执行文件所在的当前目录,PTYHONPATH(环境变量))
1 >>> import sys
2 >>> sys.path
3 ['', 'C:\\Python3\\python35.zip', 'C:\\Python3\\DLLs', 'C:\\Python3\\lib', 'C:\\Python3', 'C:\\Python3\\lib\\site-packages']
4 >>>

 1.5 if __name__ == '__main__':语句

  • if __name__ == '__main__':语句是在python脚本(模块)最后执行的,可以通过模块的全局变量__name__来查看模块名。
  • 作用:在执行脚本的时候会执行此语句,因为在执行脚本的时候全局变量__name__=='__main__',但是在被当作模块导入的时候,__name__=='导入的模块名',一般用于脚本内测试会执行,当作模块导入的时候不会执行。

  例如源文件如下,文件名test.py:

1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 
4 def run():
5     print('123')
6     print(__name__)
7 
8 if __name__ == '__main__':
9     run()

  当作脚本运行时的结果:

C:\Users\Administrator>python test.py
123
__main__

  当作模块导入的运行结果:

C:\Users\Administrator>python
Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> test.run()
123
test
>>>

 

2.包

2.1 包的概念

  • python程序由包(package)、模块(module)和函数组成。模块是一系列函数组成,而包则是一系列模块的组合。
  • 特点:

  1.包含一个__init__.py的文件夹,导入包其实就是导入__init__.py文件。
  2.包只是模块的一种封装模式,也可以理解为模块。只是把模块用文件夹封装。
  3.不同包下的同名模块在导入的时候也不会冲突。

2.2 导入包的示例

2.2.2 from ... import ...
  • from ... import ... 导入文件时,比如from a.b.c import d ,这里abc都是包名,而d则是最后一个包里的函数,切记。
2.2.3 from ... import *
  • from ... import * 导入所有文件时,比如from a.b.c import * 则会导入c这个包里的所有内容,包也能限制导入哪一个,可以回忆下定制模块导入的内置方法,__all__,在包里可以在__init__.py中定义__all__=['方法1','方法2',‘方法3’],当使用from a.b.c import * 会导入c中的'方法1','方法2',‘方法3’。
2.2.4 __init__.py文件
  • 不管是哪种方式,只要是第一次导入包或者是包的任何其他部分,都会首先执行包下的__init__.py文件,这个文件可以为空,但是也可以存放一些初始化包的代码。
2.2.5  绝对导入和相对导入
  • 绝对导入和相对导入类似于linux下的绝对路径和相对路径,比如我的绝对导入路径是,from a.b.c import d ,这时候我在b的包中想导入包的内容,就可以用from ..a import 'a下的内容'。
2.2.6 import
  • 单独导入包名称时不会导入包中所有包含的所有子模块,如我的包目录为/a/b/c  ,这时候我运行import a,但是我执行a.b.c.d()的时候,会报AttributeError异常,这个时候的解决办法是:在a包目录下的__init__.py文件中写入from . import b,并且在b的目录下的__init__.py文件中写入from . import c

3.常用模块介绍

3.1 os模块

 1 os.getcwd()                            获取当前工作目录,即当前python脚本工作的目录路径
 2 os.chdir("dirname")                    改变当前脚本工作目录;相当于shell下cd
 3 os.curdir                              返回当前目录: ('.'),相当于shell的cd .
 4 os.pardir                              获取当前目录的父目录字符串名:('..'),可以结合os.chdir(os.pardir)返回上层目录。相当于shell的cd ..
 5 os.makedirs('dirname1/dirname2')       可生成多层递归目录,相当于shell中mkdir -p
 6 os.removedirs('dirname1')              若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
 7 os.mkdir('dirname')                    生成单级目录;相当于shell中mkdir dirname
 8 os.rmdir('dirname')                    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
 9 os.listdir('dirname')                  列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
10 os.remove()                            删除一个文件
11 os.rename("oldname","newname")         重命名文件/目录
12 os.stat('path/filename')               获取文件/目录信息
13 os.sep                                 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
14 os.linesep                             输出当前平台使用的行终止符,win下为"\r\n",Linux下为"\n"
15 os.pathsep                             输出用于分割文件路径的字符串 win下为 ';',Linux下为 ':'
16 os.name                                输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
17 os.system("bash command")              运行shell命令,直接显示
18 os.environ                             获取系统环境变量
19 os.path.abspath(path)                  返回path规范化的绝对路径
20 os.path.split(path)                    将path分割成目录和文件名二元组返回
21 os.path.dirname(path)                  返回path的目录。其实就是os.path.split(path)的第一个元素
22 os.path.basename(path)                 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
23 os.path.exists(path)                   如果path存在,返回True;如果path不存在,返回False
24 os.path.isabs(path)                    如果path是绝对路径,返回True
25 os.path.isfile(path)                   如果path是一个存在的文件,返回True。否则返回False
26 os.path.isdir(path)                    如果path是一个存在的目录,则返回True。否则返回False
27 os.path.join(path1[, path2[, ...]])    将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
28 os.path.getatime(path)                 返回path所指向的文件或者目录的最后存取时间
29 os.path.getmtime(path)                 返回path所指向的文件或者目录的最后修改时间
30 os.path.getsize(path)                  返回path的大小
os模块常用方法

3.2 sys模块

 1 sys.argv                     命令行参数List,第一个元素是程序本身路径,例如执行python test.py 1 2 3,len(sys.argv)==4,sys.argv[0]是test.py,sys.argv[1]是1 ...
 2 sys.exit(n)                  退出程序,正常退出时exit(0)
 3 sys.version                  获取Python解释程序的版本信息
 4 sys.maxint                   最大的Int值
 5 sys.path                     返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值sys.platform       返回操作系统平台名称
 6 sys.getdefaultencoding()     获取系统当前编码,一般默认为'utf-8' 7 sys.stdin                    标准输入
 8 sys.stdout                   标准输出
 9 sys.stderr                   错误输出
10 sys.stdout.flush()           如果一个程序是1s输出一次,默认系统会每隔一段时间一起输入,这句的意思是实时输出。
sys模块常用方法

 3.3 random模块

 1 import random
 2  
 3 print(random.random())          #用于生成一个0到1的随机符点数: 0 <= n < 1.0
 4 print(random.randint(1,2))      #用于生成一个指定范围内的整数
 5 print(random.randrange(1,10))   #从指定范围内,按指定基数递增的集合中获取一个随机数
 6 print(random.uniform(1,10))     #用于生成一个指定范围内的随机符点数
 7 print(random.choice('zhagnsan'))    #从序列中获取一个随机元素
 8 li = ['zhangsan','lisi','wangwu']
 9 random.shuffle(li)              #用于将一个列表中的元素打乱
10 print(li)
11 li_new = random.sample(li,2)    #从指定序列中随机获取指定长度的片断(从li中随机获取2个元素,作为一个片断返回)
12 print(li_new)
random模块常用方法
 1 #随机取五位验证码,大小写字母加数字,字母和数字出现的概率相等
 2 
 3 def vcode():
 4     ret = ""
 5     for i in range(5):
 6         num = random.randint(0,9)                 #随机从(0-9)取一个数字  
 7         zimu = chr(random.randint(65,122))        #随机从大小写字母取一个字母
 8         result = str(random.choice([num,zimu]))   #字母和数字出现的概率相等
 9         ret += result
10     return ret
11 print(vcode())
random随机数示例

3.4 time模块

  • 在python中表现时间的方式有三种:

  1.时间戳

  2.结构化时间

  3.字符串时间

  对于计算机来说只认识时间戳,对于我们来说,能看懂的是结构化时间和字符串时间。time模块其实就是这三种方式之间的转换而已。

  图形化3种类转换示例:

  

  转换示例:

 1 >>> import time
 2 #时间戳格式(时间戳表示的是从1970年1月1日00:00:00开始按秒计算到现在)
 3 >>> print(time.time())
 4 1502637958.9958205
 5 >>> 
 6 
 7 #结构化时间格式(本地时间)
 8 >>> print(time.localtime())
 9 time.struct_time(tm_year=2017, tm_mon=8, tm_mday=13, tm_hour=23, tm_min=24, tm_sec=55, tm_wday=6, tm_yday=225, tm_isdst=0)
10 #结构化时间(格林威治时间,标准时间)
11 >>> print(time.gmtime())
12 time.struct_time(tm_year=2017, tm_mon=8, tm_mday=13, tm_hour=15, tm_min=25, tm_sec=7, tm_wday=6, tm_yday=225, tm_isdst=0)
13 >>> 
14 
15 
16 ###开始转换###
17 #将结构化时间转换成时间戳
18 >>> print(time.mktime(time.localtime()))
19 1502638217.0
20 >>> 
21 #将结构化时间转换成字符串时间
22 >>> print(time.strftime("%Y-%m-%d %X",time.localtime())) #X代表%H-%M-%S
23 2017-08-13 23:35:20
24 >>> 
25 #将字符串时间转换为结构化时间
26 >>> print(time.strptime("2017-08-13 23:35:20","%Y-%m-%d %X"))
27 time.struct_time(tm_year=2017, tm_mon=8, tm_mday=13, tm_hour=23, tm_min=35, tm_sec=20, tm_wday=6, tm_yday=225, tm_isdst=-1)
28 >>> 
三种方式时间转换示例

  固定字符串转换("Sun Aug 13 23:39:08 2017" 转换成这样的格式):

  图形化示例:

  

  转换示例:

 1 #结构化时间转换成固定的字符串表达时间
 2 import time
 3 >>> print(time.asctime()) #asctime参数为空,默认参数为time.localtime(),所以转化的是结构化时间
 4 Sun Aug 13 23:47:23 2017
 5 >>> 
 6 
 7 #时间戳转换成固定的字符串表达时间
 8 >>> print(time.ctime())   #ctime参数为空,默认参数为time.time(),所以转化的是时间戳
 9 Sun Aug 13 23:50:11 2017
10 >>> 
转换为固定字符串示例

3.5 json&pickle模块

序列化:

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

方法:

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

方法的特性:

  • dumps可以把特定的对象序列化处理为字符串
  • loads可以把序列化的字符串进行反序列化成相应的类型
  • dump和load其实和dumps和loads是一样的原理,唯一不同的以下用示例介绍。

区别:

  1.json可以在任何支持json格式的地方转换,而pickle只能用于python当中。

  2.在json里dump文件是以字符串形式存储的,而pickle是以字节的方式存储的。

json的使用方法:

  1. 把字典转换成json形式的字符串写入文件中 (用两种方法演示dumps和dump)

  方法一(dumps):

1 import json
2 dic = {'name': 'zhangsan'}
3 dic = json.dumps(dic)           #将dic转换成json格式
4 f = open("hello", "w")
5 f.write(dic)                    #将json格式内容写入文件

  方法二(dump)

1 import json
2 dic = {'name': 'zhangsan'}
3 f = open("hello", "w")
4 dic = json.dump(dic, f)  #将文件对象和dic对象直接格式化并写入文件

  结果:

1 {"name": "zhangsan"}

  总结:dump和dumps的区别在于dump是将字典直接序列号并写入文件,而dumps是先生成json对象,然后再写入文件,推荐使用后者。

  2.把文件中json类型的字符串读取出来转换成字典(用两种方法演示loads和load)

  方法一(loads):

1 import json
2 f = open('hello','r')
3 f = json.loads(f.read())    #读取文件对象,然后进行loads格式化。
4 print(f)
5 print(type(f))

  方法二(load):

1 import json
2 f = open('hello','r')
3 f = json.load(f)   #直接将文件进行load操作
4 print(f)
5 print(type(f))

  结果:

1 {'name': 'zhangsan'} 
2 <class 'dict'>  

  总结:load和loads的区别在于load是直接将文件进行load操作,而loads是将文件读取的内容进行loads操作,推荐使用后者。

  

json的dumps,loads,dump,load功能总结:

  • json.dumps(x)    把python的(x)原对象转换成json字符串的对象,主要用来写入文件。
  • json.loads(f)       把json字符串(f)对象转换成python原对象,主要用来读取文件和json字符串
  • json.dump(x,f)  把python的(x)原对象,f是文件对象,写入到f文件里面,主要用来写入文件的
  • json.load(file)  把json字符串的文件对象,转换成python的原对象,只是读文件

pickle和json的使用方法相同,使用可以参考json示例。

3.6 hashlib模块

  • hashlib 模块提供了很对加密算法,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法。

  特点:

  1. 内容相同则hash运算结果相同,内容稍微改变则hash值则变
  2. 不可逆推
  3. 相同算法:无论校验多长的数据,得到的哈希值长度固定。
  4. 明文变成密文,不能反解

  用途:

  • 一般数据库密码是hash值
  • 文件在网络上传输验证文件是否被篡改用hash值

  以下只用md5方式加密来介绍(其他方式只是换个加密算法就可以):

 1 import hashlib
 2 m = hashlib.md5()                 #这里可以使用以上的任意算法,算法越复杂,验证时间越长
 3 m.update('hello'.encode('utf8'))  #将字符串hello转换成md5加密后串
 4 print(m.hexdigest())              #打印md5加密串,值为5d41402abc4b2a76b9719d911017c592
 5 
 6 
 7 #注意:把一段很长的数据update多次,与一次update这段长数据,得到的结果一样
 8 ########################################################################################
 9 import hashlib
10 m = hashlib.md5()
11 m.update('hello'.encode('utf8'))  
12 print(m.hexdigest())            #hello字符串,md5值为5d41402abc4b2a76b9719d911017c592
13 m.update('world'.encode('utf8'))
14 print(m.hexdigest())            #字符串,md5值为fc5e038d38a57032085441e7fe7010b0
15 
16 ########################################################################################
17 n = hashlib.md5()
18 n.update('helloworld'.encode('utf8')) 
19 print(n.hexdigest())            #字符串helloworld,md5值为fc5e038d38a57032085441e7fe7010b0,可见持续的update等于拼接字符串之后的md5
20 ########################################################################################
md5加密示例

  以上的加密算法存在缺陷,相同的字符串的hash值永远不变,这就意味着可以生成一大堆密码的hash来反解,这种方法叫做撞库。

  示例如下:

 1 import hashlib
 2 
 3 obj = hashlib.md5()
 4 obj.update("admin".encode("utf8"))
 5 print(obj.hexdigest())  #21232f297a57a5a743894a0e4a801fc3
 6 #以上假如我知道了admin的md5是21232f297a57a5a743894a0e4a801fc3,那么以后我看到这个md5就知道是admin,这叫撞库反解。
 7 
 8 #解决办法
 9 import hashlib
10 
11 obj = hashlib.md5("aaabbbccc".encode("utf8"))   #这种方式叫加盐,给别人加上破解的难度
12 obj.update("admin".encode("utf8"))
13 print(obj.hexdigest())  #9887ad575ac3affc801e3ede4c447c5d
14 #总结:加盐之后得出的md5其实就是"aaabbbcccadmin"的md5字符串。
撞库示例

  如果还是觉得不安全的话,可以用一个更安全的模块来解决,这个模块叫hmac。

  hmac模块示例:

 1 import hmac
 2 
 3 #例一(两次追加的md5)
 4 h1=hmac.new('aabbcc')
 5 h1.update('hello')
 6 h1.update('world')
 7 print(h1.hexdigest())
 8 d9b9beb880d9451d1f90526897640f6e
 9 #例二(两次追加合并的md5)
10 h2=hmac.new('aabbcc')
11 h2.update('helloworld')
12 print(h2.hexdigest())
13 d9b9beb880d9451d1f90526897640f6e
14 #例三(合并hmac.new,可见hmac.new并不是拼接就能得到,它内部对我们创建key和内容再进行了加密处理。)
15 h3=hmac.new('aabbcchelloworld')
16 print(h3.hexdigest())
17 d77fd6f3df4f2420845c0d5431b488bc
hmac示例

3.7 shutil模块

  • 高级的 文件、文件夹、压缩包 处理模块
 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 # @Author  : All is well
 4 # @File    : shutil示例.py
 5 # @Software: PyCharm
 6 
 7 import shutil
 8 #将文件内容拷贝到另一个文件中
 9 shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))
10 
11 #拷贝文件,目标文件无需存在
12 shutil.copyfile('old.xml', '1.log')
13 
14 #仅拷贝权限。内容、组、用户均不变
15 shutil.copymode('old.xml', '1.log')
16 
17 #仅拷贝状态的信息,包括:mode bits, atime, mtime, flags,目标文件必须存在
18 shutil.copystat('f1.log', 'f2.log')
19 
20 #拷贝文件和权限
21 shutil.copy('a.log', 'b.log')
22 
23 #拷贝文件和状态信息
24 shutil.copy2('a.log', 'b.log')
25 
26 #递归的去拷贝文件夹,目标目录不能存在,222的父目录必须有w权限,ignore的意思是排除
27 shutil.copytree('111','222',ignore=shutil.ignore_patterns('a.txt','tmp*'))
28 
29 #通常的拷贝都把软连接拷贝成硬链接,即对待软连接来说,创建新的文件
30 shutil.copytree('f1', 'f2', symlinks=True, ignore=shutil.ignore_patterns('*.txt', 'tmp*'))
31 
32 #递归的去删除文件
33 shutil.rmtree('tmp')
34 
35 #递归的去移动文件,它类似mv命令,其实就是重命名。
36 shutil.move('111', '222')
37 
38 # 将 /data 下的文件打包放置当前程序目录
39 ret = shutil.make_archive("data_bak", 'gztar', root_dir='/data')
40 
41 # 将 /data下的文件打包放置 /tmp/目录
42 ret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data')
43 
44 #=============================================================
45 import zipfile
46 
47 # 压缩
48 z = zipfile.ZipFile('aaa.zip', 'w')
49 z.write('a.log')  #指定打包文件a.log
50 z.write('data')   #指定打包文件data目录
51 z.close()
52 
53 # 解压
54 z = zipfile.ZipFile('aaa.zip', 'r')
55 z.extractall(path='.') #解压到当前目录
56 z.close()
57 #=============================================================
58 
59 import tarfile
60 
61 # 压缩
62 t=tarfile.open('aaa.tar','w')
63 t.add('a.log',arcname='a.bak') #arcname指定打包内的名字
64 t.add('/test1/',arcname='test.dir')
65 t.close()
66 
67 
68 # 解压
69 t=tarfile.open('aaa.tar','r')
70 t.extractall('/tmp') #解压到tmp目录
71 t.close()
72 
73 #=============================================================
shutil示例

3.8 logging模块

3.9 configparse模块

3.10 re模块

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

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

普通字符:大多数字符和字母都会和自身匹配,如 print(re.findall('abc', 'abcdefg'))结果:['abc']

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

元字符之. ^ $ * + ? { }

 1 import re
 2 
 3 ret = re.findall('a..d','abcdefg') #.匹配单个字符
 4 print(ret) #['abcd']
 5 
 6 ret=re.findall('^a...e','abcdefgabcdefg') #^匹配字符以谁开头
 7 print(ret) #['abcde']
 8 
 9 ret=re.findall('a...e$','abcdefgabcdefgabcde') #^匹配字符以谁结尾
10 print(ret) #['abcde']
11 
12 ret=re.findall('abc*','abcccc') #贪婪匹配[0,+oo]
13 print(ret) #['abcccc']
14 
15 ret=re.findall('abc+','abccc') #[1,+oo]
16 print(ret)#['abccc']
17 
18 ret=re.findall('abc?','abccc') #[0,1]
19 print(ret)#['abc']
20 
21 ret=re.findall('abc{1,4}','abcabccabcccabccccabccccc') #匹配前一个字符m次,或者m到n次
22 print(ret)#['abc', 'abcc', 'abccc', 'abcccc', 'abcccc'] 贪婪匹配
23 
24 # 注意:前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配
25 ret=re.findall('abc*?','abcccccc') #惰性匹配
26 print(ret) #['ab']

元字符之字符集[]

 1 import re
 2 
 3 ret=re.findall('a[bc]d','abdacd')
 4 print(ret) #['abd', 'acd']
 5 
 6 ret=re.findall('[.*+?${1,3}]','a.cd+')
 7 print(ret) #['.', '+']
 8 
 9 #注意:在字符集里有功能的符号: - ^ \
10 
11 ret=re.findall('[1-9]','1a2bc3def') #1-9任意数字都匹配。
12 print(ret) #['1', '2', '3']
13 
14 ret=re.findall('[a-z]','abcd')
15 print(ret) #['a', 'b', 'c', 'd'] a-z任意一个都匹配。
16 
17 ret=re.findall('[^ab]','asdfbasdf') #非a或者非b的字符。
18 print(ret) #['s', 'd', 'f', 's', 'd', 'f']
19 
20 ret=re.findall('[^0-9]','1a2b3c4d') #非数字的字符。
21 print(ret) #['a', 'b', 'c', 'd']

元字符之转义符\

 1 # 反斜杠后边跟元字符去除特殊功能,比如\.
 2 # 反斜杠后边跟普通字符实现特殊功能,比如\d
 3 #
 4 # \d  匹配任何十进制数;它相当于类 [0-9]。
 5 # \D 匹配任何非数字字符;它相当于类 [^0-9]。
 6 # \s  匹配任何空白字符;它相当于类 [ \t\n\r\f\v]。
 7 # \S 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]。
 8 # \w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
 9 # \W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]
10 # \b  匹配一个特殊字符边界,比如空格 ,&,#等
11 import re
12 ret=re.findall('\d','1a2b3c4d') #匹配任何十进制数
13 print(ret) #['1', '2', '3', '4']
14 
15 ret=re.findall('\D','1a2b3c4d') #匹配任何非数字字符
16 print(ret) #['a', 'b', 'c', 'd']
17 
18 ret=re.findall('\s','I am \tall \nis \rwell') #匹配任何空白字符
19 print(ret) #[' ', ' ', '\t', ' ', '\n', ' ', '\r']
20 
21 ret=re.findall('\S','I am \tall \nis \rwell') #匹配任何非空白字符
22 print(ret) #['I', 'a', 'm', 'a', 'l', 'l', 'i', 's', 'w', 'e', 'l', 'l']
23 
24 ret=re.findall('\w','123abc.?${}*+') #匹配任何字母数字字符
25 print(ret) #['1', '2', '3', 'a', 'b', 'c']
26 
27 ret=re.findall('\W','123abc.?${}*+') #匹配任何非字母数字字符
28 print(ret) #['.', '?', '$', '{', '}', '*', '+']
29 
30 #这里要匹配单独的I,
31 ret=re.findall('I\b','hello I am LIST') #原理上是I后面有个空格匹配。可以匹配上
32 print(ret) #[] 但是匹配失败,为什么呢?
33 #解决办法一
34 ret=re.findall('I\\b','hello I am LIST')
35 print(ret) #['I'] 匹配成功
36 #解决办法二
37 ret=re.findall(r'I\b','hello I am LIST')
38 print(ret) #['I'] 匹配成功
39 
40 #为什么呢?
41 # 因为\b本身就是特殊字符,我们要把它解释成他自己的意思,所以I\\b才是真正要匹配的
42 # 而对于r'I\b',这个r是RawString的意思,r只对其内的反斜杠起作用(注意单个 \ 的问题),这个r会自动将其内的\转义
43 
44 #这里要匹配a\c
45 ret=re.findall('a\\c','abca\cabcd') #正常情况下我么会认为a\\c就能匹配到。
46 print(ret) #[] 匹配失败
47 
48 # 为什么呢?
49 # 因为a\\c只是针对re的转义,没错,但是python解析器也认为\是转义字符,所以我们的匹配规则应该是a\\\\c
50 ret=re.findall('a\\\\c','abca\cabcd') #正常情况下我么会认为a\\c就能匹配到。
51 print(ret) #['a\\c'] 匹配成功
52 # 根据前面匹配I,我们可以这样做。
53 ret=re.findall(r'a\\c','abca\cabcd') #正常情况下我么会认为a\\c就能匹配到。
54 print(ret) #['a\\c'] 匹配成功

元字符之分组()以及元字符之|

 1 import re
 2 
 3 ret = re.findall(r'(ad)+', 'add') #匹配0个或1个ab
 4 print(ret) #['ad']
 5 
 6 ret = re.findall('(ab)+123','ababab123') #匹配到末尾的ab123中的ab,只取分组中的内容
 7 print(ret) #['ab']
 8 
 9 ret = re.findall('(?:ab)+123','ababab123') #findall的结果不是匹配的全部内容,而是组内的内容,?:可以让结果为匹配的全部内容
10 print(ret) #['ababab123']
11 
12 
13 ret=re.search('(?P<id>\d{2})/(?P<name>\w{3})','23/com')
14 print(ret.group()) #23/com
15 print(ret.group('id')) #23
16 print(ret.group('name')) #com
17 
18 
19 # 元字符之|
20 ret=re.findall('compan(y|ies)','companiesasdfsadfcompanysadfasdaf')
21 print(ret) #['ies', 'y'] |是或的意思,结合分组,匹配ies或y
22 
23 ret=re.findall('compan(?:y|ies)','companiesasdfsadfcompanysadfasdaf')
24 print(ret) #['companies', 'company'] |是或的意思,结合分组以及?: 匹配完整。

 

 

 

posted @ 2017-08-10 01:47  Mr.gaofubin  阅读(262)  评论(0)    收藏  举报