内置常用模块详解:
1 time
2 datetime
3 random
4 os
5 sys
6 shutil
7 shelve
8 xml
9 configparser
10 hashlib
11 re
我们先来讨论下什么是模块,该怎么用,有什么用法:
定义:
用来从逻辑上组织pyhton代码(变量,函数,累,逻辑:实现一个功能),本质就是.py结尾的python 文件,模块的名字就是文件名去掉.py
使用方法:
在python文件头部导入即可,如下:
import time
我们来实践一下:
写一个简单模块:
yang_mod.py
1 name = "yang" 2 3 def hello(): 4 print("in the hello,dont hello")
新建一个test.py文件并导入yang_mod 这个模块:
1 import yang_mod 2 print(yang_mod.name) 3 yang_mod.hello()
运行得到如下结果:
可以看到在使用模块的时候要先导入,使用模块里的变量或者函数需要指定是哪个模块里的用. 做分隔符
当然我们也可以只导入模块中的一个函数或变量,当我们只需要name 这个变量时,我们只需导入模块中的name 即可:
可以看到这样导入的使用方法就变成了直接使用name
这样就会有一个问题,如果文件中有这个变量或者函数,那么原来导入的还能使用吗?
经过实践,是不能使用的,所以不建议使用 from 来导入模块当然你可以通过给导入的模块赋予一个别名的方式来使用:
关键字 as
那么上面的name 失效究竟是什么原因呢?这里让我们说一下模块导入的实质是什么?
先说下python 是解释型语言,在运行的时候会从上往下一行一行解释运行,这就是为什么要把依赖的模块写到文件头部的原因
在你import yang_mod 的时候python 做了什么?
其实python 就是把yang_mod 的文件整个执行了一遍,并把里面的所有code 赋予给了 yang_mod 这个模块名,当你下面如果还定义了这个变量的时候就会覆盖掉原来定义的,所以不能有和模块重复的定义
这里要说下 python 查找模块的顺序,当你import 一个模块时,python 会先到当前目录下寻找这个模块,如果这里没有就会在系统变量里查找,如果系统变量里也没有,python 就会报错,因为他找不到这个文件
所以当你使用一个自定义模块时要记得把模块的路径放到系统变量里。
模块到这里基本讲解完毕,下面说下和模块类似的一个东西叫包:
什么是包:
包就是一些特定的模块存放的目录,不同于目录的是包的目录下面有一个__init__.py 文件
如何使用:
和import module_name 相同,我们只需要import packages_name 即可,实践一下
我们创建一个简单的包test_packages,把原来的模块yang_mod放到这个包里:
看这个包目录下多了一个__init__.py 文件,那这个文件是干啥用的呢?我们先不管他
我们从 test.py 文件来调用 test_packages 下的yang_mod 模块里的hello() 函数,如下:
运行报错,这是为啥呢???
这就是包和模块的导入原理的区别了,模块导入是直接执行那个模块的文件,并把所有的代码赋予给了模块名称,但是包呢?实质是运行了__init__.py 这是也这个文件存在的目的。
但我们刚创建的包里这个文件是空的,所以运行的时候python 并不能找到包test_packages 下的yang_mod 这个模块,因为你要在__init__.py声明,这个包里都有哪些模块。
ok 让我们来修改这个文件:
再次运行test :
ok ,这就是包的自定义及导入和使用的方法。
python 中有很多模块,分类为:
1 标准库
即python 自带的一些模块,这些模块不需要安装,直接从文件头部import 就可以用,例如 sys os time 模块等
2 第三方库
第三方库其实就是别人做好的具有特定功能的一些模块,他们把这些模块放到网上供有需要的人下载使用,第三方库很牛逼,有太多有用的库,这也是为什么python 可以做很多事的原因,太多的库可以做太多的事情。
3 自定义库
所谓自定义库就是自己写的一些满足自己需求的模块,你把他放到网上供别人使用的话在别人眼里这就是第三方库。。
ok 库的分类讲完,我们来学习一些标准库:
1 time
如名字一样,就是时间。
在python 中 时间分为三种表达方式:
1 特定格式的字符串形式:
如 2016-08-08 20:35:25 自己定义的一些格式
2 时间戳,即Unix 时间,下面是wiki 的解释:
3 元组形式的时间:
即执行 time.localtime 返回一个元组形式的时间
下面是他的一些使用方法:
1 import time 2 3 #time模块 4 print("本地时区的元组时间") 5 print(time.localtime()) 6 print("标准时区的元组时间") 7 print(time.gmtime()) 8 print("从元组时间中获取值") 9 x = time.localtime() 10 print("从元组时间中获取小时") 11 print(x.tm_hour) 12 print("从元组时间中获取年") 13 print(x.tm_year) 14 print("把元组转换为时间戳") 15 print(time.mktime(x)) 16 print("把元组转换为自定义格式的时间") 17 print(time.strftime("%Y-%m-%d",x)) 18 print("把自定义格式的时间再转换回元组") 19 print(time.strptime("2016-08-20","%Y-%m-%d")) 20 print("转换为一个asc格式的时间") 21 print(time.asctime())
变量:
本地时间和世界标准时间的差值 单位秒
下面是不同格式时间间转换的方法:
从元组形式的时间中获取数据: 元组里的都可以获取
把元组形式时间转换为时间戳格式:
2 datetime #扩展的时间
可以获取任意时间,比如三天后时间:
1 # print("三天后时间") 2 # print(datetime.datetime.now() + datetime.timedelta(3))
3 random 模块
一句话,获取随机数。
最基础的使用,默认获取从0到1的浮点数:
1 import random 2 print(random.random())
随机获取指定整数之间数字:
1 print(random.randint(1,10))
获取指定整数之间的数字,并指定间隔: ##记住range 是顾头不顾尾
1 import random 2 print(random.randrange(1,10,2))
随机获取指定整数之间的浮点数:
1 import random 2 print(random.uniform(1,10))
随机字符串及随机多个字符串,多个字符串结果为列表:
1 # Author: Shen Yang 2 import random 3 print(random.choice("dsaflksfklasdflkasl")) 4 print(random.sample("dsaflksfklasdflkasl",4))
另外,还有一个类似于洗牌的功能,把列表顺序打乱,每次都不一样:
1 import random 2 list1 = [1,2,3,4,5,6,7,8,9] 3 print("打乱前:",list1) 4 random.shuffle(list1) 5 print("打乱后:",list1)
随机数random 就这几个方法,那我们怎么用它来写一个验证码生成程序呢?
想获取4个英文和数字混合的验证码:
可以先定义一个空变量,然后循环四次,每次的值不相同,每次都追加进之前定义好的空变量里,循环完毕后打印空变量
1 import random 2 3 checkcode = '' 4 for i in range(1,5): 5 tmp = random.randrange(1,5) 6 if i == tmp: 7 tmp = str(random.randint(0,9)) 8 else: 9 tmp = chr(random.randint(69,90)) 10 checkcode += tmp 11 12 print(checkcode)
ok 随机验证码的需求得到满足。。。。
4 os 模块
打印当前目录:
1 import os 2 print(os.getcwd())
切换目录:
1 import os 2 print(os.getcwd()) 3 print("切换到上级目录") 4 os.chdir('..') 5 print(os.getcwd())
windows 下使用r转意:
递归创建目录: #原理就是不停的调mkdir 来创建
递归删除空目录: #清理空文件夹用的
创建目录: #windows 下使用r转意
删除空目录: #非空不会删除
列出目录中包含的内容: #是列表格式
删除一个文件:
重命名文件或目录:
查看文件属性: #返回元组形式
输出操作系统的特定路径分割符:
输出操作系统的特定的换行符:
输出系统的环境变量: #kv 格式
查看平台:
执行命令:
返回文件的相对路径及文件名: #元组格式
获取文件所在目录名称:
获取文件名:
判读路径是否存在:
是否为绝对路径:
是否为文件:
是否为目录:
组合为路径: #windows 有bug
获取文件的各个详细时间:
5 sys模块
比较重要的是sys.argv 用来获取用户传入的参数
6 shutil 模块:
可以复制文件,可有多种复制选项,比如权限等 还可以压缩,解压文件,有多种格式可选:
拷贝:
从原文件读取数据写到新文件
复制原文件到新文件
shutil.copyfile
递归拷贝:
递归删除: #这里比os.removedirs() 要高效
压缩文件:
zip 的压缩与解压
tar 包的压缩与解压
通过以上我们看到,我们也可以自己去使用这些模块自己去压缩文件。
7 shelve 简单的kv 持久化 只支持python pickle 格式
持久化:
自动生成三个文件:
获取:
8 xml
更改xml文件
1 #!/usr/bin/env python3 2 # Author: Shen Yang 3 import xml.etree.ElementTree as ET 4 5 tree = ET.parse("data.xml") 6 root = tree.getroot() #获取根标签 7 8 #修改 9 for node in root.iter('year'): 10 new_year = int(node.text) + 1 11 node.text = str(new_year) #更改数据 12 node.set("updated","yes") #添加属性 13 14 tree.write("newdata.xml") #写入新文件
1 #删除 2 for country in root.findall('country'): #循环查找所有的country 3 rank = int(country.find('rank').text) #取出每个country下的rank的数据 4 if rank > 50: 5 root.remove(country) #删除rank值大于50的整个country 标签 6 tree.write("delcountry.xml")
1 #创建 2 new_xml = ET.Element("newcreate") 3 4 infolist = ET.SubElement(new_xml,"infolist",attrib={"enrolled":"yes"}) 5 name = ET.SubElement(infolist,"name",attrib={"checked":"no"}) 6 sex = ET.SubElement(infolist,"sex") 7 sex.text= "man" 8 age = ET.SubElement(infolist,"age") 9 age.text = "22" 10 11 et = ET.ElementTree(new_xml) 12 et.write("newcreate.xml",encoding="utf-8",xml_declaration=True) 13 ET.dump(new_xml)
9 ConfigParser模块 配置文件生成工具
生成:
1 import configparser 2 3 #生成 4 config = configparser.ConfigParser() 5 config["client"] = {"port":"3306", 6 "socket":"/usr/local/mysql/mysql.sock"} 7 config["mysqld"] = {"datadir":"/usr/local/mysql/data", 8 "port":"3306", 9 "socket": "/usr/local/mysql/mysql.sock", 10 "server-id":"1", 11 "log-bin":"mysql-bin", 12 "binlog_format":"MIXED"} 13 with open("my.cnf","w") as f: 14 config.write(f)
读取:
修改: #一般用不到,因为配置都是手工修改
10 hashlib 模块:
用来加密字符串或者给文件生成一个值来保证一致性
测试两种加密方式:
1 import hashlib 2 m = hashlib.md5() 3 m.update("中文,是否可行?".encode(encoding="utf-8")) 4 print(m.hexdigest()) 5 s = hashlib.sha512() 6 s.update("这是测试下".encode(encoding="utf-8")) 7 print(s.hexdigest())
还有一种是传入参数的加密方式:
hmac
1 import hmac 2 h = hmac.new("测试呵呵".encode(encoding="utf-8"),"中文是否可行".encode(encoding="utf-8")) 3 print(h.hexdigest())
1 正则:就是用键盘上的某些特殊符号组成规则,来匹配某一类具有共同特性的字符串 2 3 举例: 4 规则一:世界上四条腿的事物---->椅子,老虎,鳄鱼 5 规则二:世界上四条腿并且能坐的事物----->椅子 6 7 8 ^:代表以某个字符开头 9 例如规则:^a 10 意义:匹配任何以a开头的字符串,那么字符串a123,abc,a1bc都符合条件 11 12 $:代表以某个字符结尾 13 例如规则:a$ 14 意义:匹配任何以a结尾的字符串,那么字符串123a,ddda,abcdda都符合条件 15 16 *:代表前置字符有0个或者无穷个 17 例如规则:ab* 18 意义:匹配包含有0个b或者无穷个b的字符串,那么ab,abb,abbbb,都会被匹配到,但是bbbb不会被匹配 19 20 +:代表前置字符有1个或者无穷个 21 22 {m}:代表前置字符有m个 23 例如:a{3} 24 意义:匹配包含3个连续a的字符串,那么123aaa1233,aaa123,123aaa,都会被匹配到 25 26 {m,n}:代表前置字符有m到n个 27 28 {m,}:代表前置字符有m到无穷个 29 30 .:代表匹配任意一个字符 31 32 ?:代表前置字符有0个或者1个 33 34 []:中括号里可以写字符,代表从你写入的一大堆字符中只匹配一个 35 规则:a[x=,1]b 36 意义:可以匹配到axb或a=b或a,b或者a1b 37 38 [^]:基于[]取反
39 规则:a[0-9]b 40 意义:a0b,a1b,a2b等都可以被匹配 41 42 规则:a[^0-9]b 43 意义:ab中间必有字符,但是该字符一定不能是数字,于是azb,adb,a=b等都被匹配到
re 的匹配方法:
re.match #从头开始匹配
re.search #匹配包含
re.findall 把所有匹配到的字符放到以列表中的元素返回
re.splitall 以匹配到的字符当做列表分隔符
re.sub 匹配字符并替换
只要有返回就是匹配到了,没返回就是没有匹配到。
匹配数字: /d
使用 re.search 匹配一行里的指定的
?匹配前面字符一次或0次 也就是前面的一个字符没有也行
findall 没有 group 方法
使用括号分组:
管道符要转意:
\A 开头 \Z 结尾 和 ^ $ 一样
\D 非数字 任何非数字的都可以匹配到,包括空格换行等
\w 匹配[A-Za-z0-9] \W 非 [A-Za-z0-9]
\s 匹配空白字符、\t、\n、\r
匹配多个分组:
用 字典获取:
或者直接复制获取
一个典型例子:
通过分组把身份证获取到字典中:
split 通过指定分隔符来分组
sub 替换 把匹配到的替换为指定的字符
2 re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
3 M(MULTILINE): 多行模式,改变
'^'
和
'$'
的行为
4 S(DOTALL): 点任意匹配模式,改变
'.'
的行为