本节内容:
- 模块介绍
- time
- random
- os
- sys
- json & picle
- shelve
- XML
- hashlib
- ConfigParser
- logging
模块介绍
在Python中,一个.py文件就称之为一个模块(Module)。
1、使用模块有好处:
- 最大的好处是大大提高了代码的可维护性。
- 编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块
2、模块分为三种:
- 自定义模块
- 内置标准模块(又称标准库)
- 开源模块
3、导入模块:
- import: 使客户端(导入者)以一个整体获取一个模块。
- from:容许客户端从一个模块文件中获取特定的变量名。
- reload:在不中止Python程序的情况下,提供了一个重新载入模块文件代码的方法。
1 import module
2
3 from module.xx.xx import xx
4
5 from module.xx.xx import xx as rename
6
7 from module.xx.xx import *
4 、运行本质
1 #1 import test
2
3 #2 from test import add
无论1还是2,首先通过sys.path找到test.py,然后执行test脚本(全部执行),区别是1会将test这个变量名加载到名字空间,而2只会将add这个变量名加载进来。
time模块
时间相关的操作,时间有三种表示方式:
- 时间戳 1970年1月1日之后的秒,即:time.time()
- 格式化的字符串 2011-11-11 11:11, 即:time.strftime('%Y-%m-%d')
- 结构化时间 元组包含了:年、日、星期等... time.struct_time 即:time.localtime()
1 import time
2
3 # 1 time() :返回当前时间的时间戳
4
5 time.time() # 1481592271.0
6
7 # ----------------------------------------------------------
8
9
10
11 # 2 localtime([secs])
12
13 # 将一个时间戳转换为当前时区的struct_time。secs参数未提供,则以当前时间为准。
14
15 print(time.localtime()) # time.struct_time(tm_year=2016, tm_mon=12, tm_mday=13, tm_hour=9,
16 # tm_min=26, tm_sec=4, tm_wday=1, tm_yday=348, tm_isdst=0)
17
18
19
20 # ----------------------------------------------------------
21
22
23
24 # 3 gmtime([secs]) 和localtime()方法类似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。
25
26
27
28 # ----------------------------------------------------------
29
30
31
32 # 4 mktime(t) : 将一个struct_time转化为时间戳。
33
34 print(time.mktime(time.localtime())) # 1481592271.0
35
36 # ----------------------------------------------------------
37
38
39
40 # 5 asctime([t]) : 把一个表示时间的元组或者struct_time表示为这种形式:'Sun Jun 20 23:21:05 1993'。
41
42 # 如果没有参数,将会将time.localtime()作为参数传入。
43
44 print(time.asctime()) # Tue Dec 13 09:26:04 2016
45
46 # ----------------------------------------------------------
47
48
49
50 # 6 ctime([secs]) : 把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式。如果参数未给或者为
51
52 # None的时候,将会默认time.time()为参数。它的作用相当于time.asctime(time.localtime(secs))。
53
54 print(time.ctime()) # Tue Dec 13 09:26:04 2016
55
56 print(time.ctime(time.time())) # Tue Dec 13 09:26:04 2016
57
58 # 7 strftime(format[, t]) : 把一个代表时间的元组或者struct_time(如由time.localtime()和
59
60 # time.gmtime()返回)转化为格式化的时间字符串。如果t未指定,将传入time.localtime()。如果元组中任何一个
61
62 # 元素越界,ValueError的错误将会被抛出。
63
64 print(time.strftime("%Y-%m-%d %X", time.localtime())) # 2016-12-13 09:26:04
65
66 # 8 time.strptime(string[, format])
67
68 # 把一个格式化时间字符串转化为struct_time。实际上它和strftime()是逆操作。
69
70 print(time.strptime('2016-12-12 12:12:00', '%Y-%m-%d %X'))
71
72
73
74 # time.struct_time(tm_year=2016, tm_mon=12, tm_mday=12, tm_hour=12, tm_min=12, tm_sec=0,
75 # tm_wday=0, tm_yday=347, tm_isdst=-1)
76
77
78
79 # 在这个函数中,format默认为:"%a %b %d %H:%M:%S %Y"。
80
81
82
83
84
85 # 9 sleep(secs)
86
87 # 线程推迟指定的时间运行,单位为秒。
88
89
90
91 # 10 clock()
92
93 # 这个需要注意,在不同的系统上含义不同。在UNIX系统上,它返回的是“进程时间”,它是用秒表示的浮点数(时间戳)。
94
95 # 而在WINDOWS中,第一次调用,返回的是进程运行的实际时间。而第二次之后的调用是自第一次调用以后到现在的运行
96
97 # 时间,即两次时间差
随机数: random模块
1 import random
2
3 print(random.random()) # 用于生成一个0到1的随机符点数: 0 <= n < 1.0
4
5 print(random.randint(1 ,2)) # 用于生成一个指定范围内的整数
6
7 print(random.randrange(1 ,10)) # 从指定范围内,按指定基数递增的集合中获取一个随机数
8
9 print(random.uniform(1 ,10)) # 用于生成一个指定范围内的随机符点数
10
11 print(random.choice('ocean')) # 从序列中获取一个随机元素
12
13 li = ['tom' ,'jack' ,'ocean' ,]
14
15 random.shuffle(li) # 用于将一个列表中的元素打乱
16
17 print(li)
18
19 li_new = random.sample(li ,2) # 从指定序列中随机获取指定长度的片断(从li中随机获取2个元素,作为一个片断返回)
20
21 print(li_new)
验证码:
import random
def v_code():
code = ''
for i in range(5):
num=random.randint(0,9)
alf=chr(random.randint(65,90))
add=random.choice([num,alf])
code += str(add)
return code
print(v_code())
os模块
os模块是与操作系统交互的一个接口:
1 import os
2 os.getcwd() #获取当前工作目录,即当前python脚本工作的目录路径
3 os.chdir("dirname") #改变当前脚本工作目录;相当于shell下cd
4 os.curdir #返回当前目录: ('.')
5 os.pardir #获取当前目录的父目录字符串名:('..')
6 os.makedirs('dirname1/dirname2') #可生成多层递归目录
7 os.removedirs('dirname1') #若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
8 os.mkdir('dirname') #生成单级目录;相当于shell中mkdir dirname
9 os.rmdir('dirname') #删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
10 os.listdir('dirname') # 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
11 os.remove() #删除一个文件
12 os.rename("oldname","newname") #重命名文件/目录
13 os.stat('path/filename') #获取文件/目录信息
14 os.sep #输出操作系统特定的路径分隔符,win下为"\",Linux下为"/"
15 os.linesep #输出当前平台使用的行终止符,win下为"
",Linux下为"
"
16 os.pathsep #输出用于分割文件路径的字符串
17 os.name #输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
18 os.system("bash command") #运行shell命令,直接显示
19 os.environ #获取系统环境变量
20 os.path.abspath(path) #返回path规范化的绝对路径
21 os.path.split(path) #将path分割成目录和文件名二元组返回
22 os.path.dirname(path) #返回path的目录。其实就是os.path.split(path)的第一个元素
23 os.path.basename(path) #返回path最后的文件名。如何path以/或结尾,那么就会返回空值。即os.path.split(path)的第二个元素
24 os.path.exists(path) #如果path存在,返回True;如果path不存在,返回False
25 os.path.isabs(path) #如果path是绝对路径,返回True
26 os.path.isfile(path) # 如果path是一个存在的文件,返回True。否则返回False
27 os.path.isdir(path) #如果path是一个存在的目录,则返回True。否则返回False
28 os.path.join(path1[, #path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
29 os.path.getatime(path) #返回path所指向的文件或者目录的最后存取时间
30 os.path.getmtime(path) # 返回path所指向的文件或者目录的最后修改时间
sys模块
sys模块用于提供对解释器相关的操作:
1 sys.argv 命令行参数List,第一个元素是程序本身路径
2 sys.exit(n) 退出程序,正常退出时exit(0)
3 sys.version 获取Python解释程序的版本信息
4 sys.maxint 最大的Int值
5 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
6 sys.platform 返回操作系统平台名称
7 sys.stdin 输入相关
8 sys.stdout 输出相关
9 sys.stderror 错误相关
手写进度条程序:
1 #手写进度条
2 import sys,time
3 for i in range(101):
4 sys.stdout.write('
') #每一次清空原行。
5 sys.stdout.write("%s%% |%s|"%(int(int(i)/100*100),int(int(i)/100*100) * '>')) #一共次数除当前次数算进度
6 sys.stdout.flush() #强制刷新到屏幕
7 time.sleep(0.03)
8 # 结果:100% |>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>|
json&pickle模块
1、什么是序列化?
我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。
序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
2、用于序列化的两个模块
- json,用于字符串 和 python数据类型间进行转换
- pickle,用于python特有的类型 和 python的数据类型间进行转换
Json模块提供了四个功能:dumps、dump、loads、load
pickle模块提供了四个功能:dumps、dump、loads、load
dump()函数接受一个文件句柄和一个数据对象作为参数,把数据对象以特定的格式保存 到给定的文件中。当我们使用load()函数从文件中取出已保存的对象时,pickle知道如何恢复这些对象到它们本来的格式。
dumps()函数执行和dump() 函数相同的序列化。取代接受流对象并将序列化后的数据保存到磁盘文件,这个函数简单的返回序列化的数据。
loads()函数执行和load() 函数一样的反序列化。取代接受一个流对象并去文件读取序列化后的数据,它接受包含序列化后的数据的str对象, 直接返回的对象。
1 # ----------------------------序列化
2
3 import json
4
5 dic = {'name': 'ocean', 'age': 18, 'sex': 'male'}
6
7 print(type(dic)) # <class 'dict'>
8
9 j = json.dumps(dic)
10
11 print(type(j)) # <class 'str'>
12
13 f = open('序列化对象.txt', 'w')
14
15 f.write(j) # -------------------等价于json.dump(dic,f)
16
17 f.close()
18
19 # -----------------------------反序列化<br>
20
21 import json
22
23 f = open('序列化对象.txt')
24
25 data = json.loads(f.read()) # 等价于data=json.load(f)
import json
#dct="{'1':111}"#json 不认单引号
#dct=str({"1":111})#报错,因为生成的数据还是单引号:{'one': 1}
dct='{"1":"111"}'
print(json.loads(dct))
#conclusion:
# 无论数据是怎样创建的,只要满足json格式,就可以json.loads出来,不一定非要dumps的数据才能loads
Pickle模块
Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。
1 ##----------------------------序列化
2
3 import pickle
4
5 dic={'name':'ocean','age':18,'sex':'male'}
6
7 print(type(dic))#<class 'dict'>
8
9 j=pickle.dumps(dic)
10
11 print(type(j))#<class 'bytes'>
12
13
14 f=open('序列化对象_pickle','wb')#注意是w是写入str,wb是写入bytes,j是'bytes'
15
16 f.write(j) #-------------------等价于pickle.dump(dic,f)
17
18 f.close()
19
20 #-------------------------反序列化
21
22 import pickle
23
24 f=open('序列化对象_pickle','rb')
25
26 data=pickle.loads(f.read())# 等价于data=pickle.load(f)
27
28
29 print(data['age'])
shelve模块
shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型
1 import shelve
2
3 f = shelve.open(r'shelve.txt')
4
5 # f['stu1_info']={'name':'tom','age':'18'}
6
7 # f['stu2_info']={'name':'jack','age':'19'}
8
9 # f['school_info']={'website':'oldboy.edu','city':'beijing'}
10
11 #
12
13 #
14
15 # f.close()
16
17 print(f.get('stu_info')['age'])
XML模块
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,xml出现的时间要远早于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协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml:
1 import xml.etree.ElementTree as ET
2
3 tree = ET.parse("xmltest.xml")
4 root = tree.getroot()
5 print(root.tag)
6
7 #遍历xml文档
8 for child in root:
9 print(child.tag, child.attrib)
10 for i in child:
11 print(i.tag,i.text)
12
13 #只遍历year 节点
14 for node in root.iter('year'):
15 print(node.tag,node.text)
16 #---------------------------------------
17
18 import xml.etree.ElementTree as ET
19
20 tree = ET.parse("xmltest.xml")
21 root = tree.getroot()
22
23 #修改
24 for node in root.iter('year'):
25 new_year = int(node.text) + 1
26 node.text = str(new_year)
27 node.set("updated","yes")
28
29 tree.write("xmltest.xml")
30
31
32 #删除node
33 for country in root.findall('country'):
34 rank = int(country.find('rank').text)
35 if rank > 50:
36 root.remove(country)
37
38 tree.write('output.xml')
创建xml:
1 import xml.etree.ElementTree as ET
2
3
4 new_xml = ET.Element("namelist")
5 name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})
6 age = ET.SubElement(name,"age",attrib={"checked":"no"})
7 sex = ET.SubElement(name,"sex")
8 sex.text = '33'
9 name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
10 age = ET.SubElement(name2,"age")
11 age.text = '19'
12
13 et = ET.ElementTree(new_xml) #生成文档对象
14 et.write("test.xml", encoding="utf-8",xml_declaration=True)
15
16 ET.dump(new_xml) #打印生成的格式
hashlib模块
用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
import hashlib
m = hashlib.md5() # m=hashlib.sha256()
m.update('hello'.encode('utf8'))
print(m.hexdigest()) # 5d41402abc4b2a76b9719d911017c592
m.update('ocean'.encode('utf8'))
print(m.hexdigest()) # 70867858919c6cea68a9afb520150c91 注意第二次update的值要连接前次值
m2 = hashlib.md5()
m2.update('helloocean'.encode('utf8'))
print(m2.hexdigest()) # 70867858919c6cea68a9afb520150c91
以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。
1 import hashlib
2
3 # ######## sha256 ########
4
5
6 hash = hashlib.sha256('sdfasd'.encode('utf8')) #加盐后撞库解密概率就低了
7
8 hash.update('ocean'.encode('utf8'))
9
10 print(hash.hexdigest()) # 57a11d808817b718aa1e7950b59cb2c7f76588e481fa34d1cc6fd01505a4aa2c
python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 再进行处理然后再加密:
import hmac
h = hmac.new('ocean'.encode('utf8'))
h.update('china'.encode('utf8'))
print (h.hexdigest())#365f8b278af5e4e16b031683fb09cfa7
ConfigParser模块
ConfigParser 是用来处理配置文件的包。配置文件的格式如下:中括号“[ ]”内包含的为section。section 下面为类似于key-value 的配置内容。
1 #创建配置文件
2 import configparser
3
4 config = configparser.ConfigParser()
5 config["DEFAULT"] = {'country': 'china',
6 'Author': 'ocean',
7 }
8
9 config['baidu.com'] = {}
10 config['baidu.com']['User'] = 'liyanhong'
11 config['server.baidu.com'] = {}
12 con = config['server.baidu.com']
13 con['Name'] = 'mayun'
14 con['F'] = 'no'
15 config['DEFAULT']['Test'] = 'yes'
16 with open('example.ini', 'w') as configfile:
17
18 config.write(configfile)
结果:
[DEFAULT] #节点
country = china
author = ocean
test = yes
[baidu.com] #节点
user = liyanhong
[server.baidu.com]#节点
name = mayun
f = no
对配置文件的增、删、改、查
1 # ----------------------------查
2
3 import configparser
4
5 config = configparser.ConfigParser()
6 config.read('example.ini',encoding='utf8')
7 print(config.sections()) #获取所有节点['baidu.com', 'server.baidu.com']
8
9 print('baidu.com' in config) #True 判断节点是否在配置文件中
10 print('mayun' in config) #False 节点下值不可直接判断
11
12 print(config['baidu.com']['user']) #取值 liyanhong
13
14 for key in config['DEFAULT']: #获取节点下所有键
15 print(key)
16 #country
17 #author
18 #test
19
20 print(config.options('server.baidu.com')) #['name', 'f', 'country', 'author', 'test']
21 #输出内容包含DEFAULT下的所有键
22
23 print(config.items('server.baidu.com'))
24 #[('country', 'china'), ('author', 'ocean'), ('test', 'yes'), ('name', 'mayun'), ('f', 'no')]
25 #以元组的形式输出键值对,包含DEFAULT下的所有键值对
26
27 print(config.get('server.baidu.com','name')) #mayun
28 #获取节点下键所对应的值,不包括DEFAULT内容
29
30 #----------------------------增、删、改
31
32 config.add_section('ocean') #增加节点[ocean]
33
34 config.remove_section('ocean') #删除节点[ocean]
35
36 config.remove_option('server.baidu.com','f') #删除指定节点下的键值对
37
38 config.set('baidu.com','user','duniang') #修改指定节点下指定键的值
39
40 config.write(open('example.ini','w')) #增删改后都需要写入文件
logging模块
logging用于便捷记录日志且线程安全的模块
logging的日志可以分为 debug(), info(), warning(), error()and critical() 5个级别
1 #简单应用
2 import logging
3 logging.debug('debug message')
4 logging.info('info message')
5 logging.warning('warning message')
6 logging.error('error message')
7 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名称:用户输出消息。
1 import logging
2
3
4 # --------------------basicConfig
5 logging.basicConfig(level=logging.DEBUG,
6 format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
7 datefmt='%a, %d %b %Y %H:%M:%S',
8 filename='logger.log',
9 filemode='w')
10
11 logging.debug('debug message')
12 logging.info('info message')
13 logging.warning('warning message')
14 logging.error('error message')
15 logging.critical('critical message')
16
17
18 # ----------------------logger
19 import logging
20
21 logger = logging.getLogger()
22 # 创建一个handler,用于写入日志文件
23 fh = logging.FileHandler('test.log')
24
25 # 再创建一个handler,用于输出到控制台
26 ch = logging.StreamHandler()
27
28 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
29 #自定义参数个数,默认level等级为warning
30
31 fh.setFormatter(formatter)
32 ch.setFormatter(formatter)
33 #logger吸星大法
34 logger.addHandler(fh) #logger对象可以添加多个fh和ch对象
35 logger.addHandler(ch)
36
37 logger.debug('logger debug message')
38 logger.info('logger info message')
39 logger.warning('logger warning message')
40 logger.error('logger error message')
41 logger.critical('logger critical message')
例一
1 import logging
2
3 ##################################################
4 logger1 = logging.getLogger('mylogger')
5 logger1.setLevel(logging.DEBUG)
6
7 logger2 = logging.getLogger('mylogger')
8 logger2.setLevel(logging.INFO)
9
10 fh = logging.FileHandler('test.log')
11 ch = logging.StreamHandler()
12
13 logger1.addHandler(fh)
14 logger1.addHandler(ch)
15
16 logger2.addHandler(fh)
17 logger2.addHandler(ch)
18
19 logger1.debug('logger1 debug message')
20 logger1.info('logger1 info message')
21 logger1.warning('logger1 warning message')
22 logger1.error('logger1 error message')
23 logger1.critical('logger1 critical message')
24
25 logger2.debug('logger2 debug message')
26 logger2.info('logger2 info message')
27 logger2.warning('logger2 warning message')
28 logger2.error('logger2 error message')
29 logger2.critical('logger2 critical message')
结果:
logger1 info message
logger1 warning message
logger1 error message
logger1 critical message
logger2 info message
logger2 warning message
logger2 error message
logger2 critical message
logger1和logger2对应的是同一个Logger实例,只要logging.getLogger(name)中名称参数name相同则返回的Logger实例就是同一个,且仅有一个,也即name与Logger实例一一对应。在logger2实例中通过logger2.setLevel(logging.INFO)设置mylogger的日志级别为logging.INFO,所以最后logger1的输出遵从了后来设置的日志级别。