一、模块
模块就是写好的功能放在一个文件里,即py文件
模块的种类:
① 内置模块:安装python解释器的时候就装上了
② 第三方模块、扩展模块:不在内置模块不一定不重要,根据用户需求安装使用
③ 自定义模块:自己写的py文件
二、序列化模块
序列:列表、元组、字符串、bytes
序列化:把一个数据类型转换成字符串、bytes类型的过程就是序列化
数据类型序列化的场景:
① 把一个数据类型存储在文件中
② 把一个数据类型通过网络传输的时候
eval和exec:用户输入,文件读入,网络传入都不能使用,存在风险,极其不安全。
import json # 导入json模块
在json格式下,所欲的字符串都是双引号。
json.dumps(obj) 序列化的过程,转换为字符串
import json # 导入json模块
dic = {'province':'广东省','city':'深圳市'}
s = json.dumps(dic) # 序列化的过程
print(s,type(s))
# {"province": "\u5e7f\u4e1c\u7701", "city": "\u6df1\u5733\u5e02"} <class 'str'>
json.loads(str) 反序列化的过程,转换为原本的类型
import json # 导入json模块
dic = {'province':'广东省','city':'深圳市'}
s = json.dumps(dic) # 序列化的过程
dic2 = json.loads(s) # 反序列化的过程
print(dic2,type(dic2))
# {'province': '广东省', 'city': '深圳市'} <class 'dict'>
json.dump(obj,f) 序列化的过程,将字典写入到文件中
import json
dic = {'a':1,'lis':[1,2,3],'city':'gz'}
f = open('aaa','a',encoding='utf-8')
json.dump(dic,f) # 把字典写入到文件中
f.close()
'''
{"a": 1, "lis": [1, 2, 3], "city": "gz"}
'''
json.load(f)
import json
f = open('aaa',encoding='utf-8')
dic = json.load(f) # 将文件的内容读取出来,并且还原原来的类型
print(dic) # {'a': 1, 'lis': [1, 2, 3], 'city': 'gz'}
json的优点:
① 所有的语言都通用
json的缺点:
① 只支持非常少的数据类型
② 对数据类型的约束很苛刻
③ 字典的key必须是字符串
④ 只支持数据类型:数字、字符串、列表、字典
使用json的场景:
序列化的内容是简单的内容,比如字典,字符串类型的就选择json,因为json有优势,可以直接看到结果,或者从文件里 能看到结果。
前端使用的是json,网络传输的数据大部分也是使用json
json的特点:
① 可以在所有的语言中通用
② 能够处理的数据类型非常优先(网络操作中,以及多语言环境中,传递字典、数字、字符串、列表等简单的数据类型时使用)
③ json的字典有非常苛刻的要求:字典的key必须是字符串,且所有的字符串都必须是用" " 表示
④ dumps(dict/list) 把dict/list 转化成str,这是序列化
⑤ loads(str) 把str转化为dict/list,这是反序列化
⑥ dump(dict/list,f) 把dict/list写入文件,这是序列化
⑦ load(f) 文件转化为原来的数据类型,这是反序列化
⑧ 多次dump进入文件中的数据load会报错
json的参数:
ensure_ascii:默认值True,如果dict内含有non-ASCII的字符,则会类似\uXXXX的显示数据,设置成False后,就能正常显示
indent:应该是一个非负的整型,如果是0,或者为空,则一行显示数据,否则会换行且按照indent的数量显示前面的空白,这样打印出来的json数据也叫pretty-printed json
separators:分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(',',':');这表示dictionary内keys之间用“,”隔开,而KEY和value之间用“:”隔开。
encoding:默认是UTF-8,设置json数据的编码方式。
sort_keys:将数据根据keys的值进行排序。
pickle
import pickle
pickle和json的用法相似。
局限性:只有python语言支持
优点:支持几乎所有的数据类型
pickle操作文件必须是以+b的形式
pickle支持多次dump和多次load,需要使用try...except
① pickle多次dump
import pickle
lis = [1,2,3,{'a':1,'b':2,'c':['a','b','c'],'d':'gz'},'z','x']
f = open('aaa','ab')
for i in range(10):
pickle.dump(lis,f) # 循环多次写入文件
f.close()
② pickle多次load
import pickle
f = open('aaa','rb')
while 1:
try:
lis = pickle.load(f)
print(lis)
except EOFError:
break
f.close()
'''
[1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
[1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
[1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
[1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
[1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
[1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
[1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
[1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
[1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
[1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
'''
三、时间模块
imprt time
三种格式:
① 时间戳时间:浮点数支撑,以秒为单位(方便计算机计算)
语法:time.time()
1970-1-1 0:0:0 格林威治时间,时间的起始点
import time
t = time.time()
print(t) # 1536047063.2101386
② 格式化时间:字符串数据类型(显示给用户看)
time。strftime(字符串格式实际)
import time
fm1 = time.strftime('%Y-%m-%d') # 年月日 2018-09-04
fm2 = time.strftime('%H:%M:%S') # 时分秒 15:48:25
fm3 = time.strftime('%c') # 外国格式 ue Sep 4 15:48:25 2018
fm4 = time.strftime('%X') # 时分秒 15:48:25
fm5 = time.strftime('%x') # 月/日/年 09/04/18
③ 结构化时间: 元组格式,用于时间戳时间和格式化时间之间的转化
time.localtime()
import time
t = time.localtime()
print(t)
'''
time.struct_time(tm_year=2018, tm_mon=9, tm_mday=4, tm_hour=15, tm_min=52, tm_sec=5, tm_wday=1, tm_yday=247, tm_isdst=0)
'''
时间格式的转化:
格式化时间 ---> 时间戳时间
fmt = time.strftime('%x %X') # 格式化时间
stt = time.strptime(fmt,'%x %X') # 结构化时间
t = time.mktime(stt) # 时间戳时间
print(fmt)
print(stt)
print(t)
'''
09/04/18 15:56:53
time.struct_time(tm_year=2018, tm_mon=9, tm_mday=4, tm_hour=15, tm_min=56, tm_sec=53, tm_wday=1, tm_yday=247, tm_isdst=-1)
1536047813.0
'''
时间戳时间 ---> 格式化时间
t = time.time() # 时间戳时间
stt = time.localtime(t) # 结构化时间
fmt = time.strftime('%Y-%m-%d %X',stt) # 格式化时间
print(t)
print(stt)
print(fmt)
'''
1536048042.169353
time.struct_time(tm_year=2018, tm_mon=9, tm_mday=4, tm_hour=16, tm_min=0, tm_sec=42, tm_wday=1, tm_yday=247, tm_isdst=0)
2018-09-04 16:00:42
'''
结构化时间 --> %a %b %d %H:%M:%S %Y串
t = time.asctime() # 结构化时间 %a %b %d %H:%M:%S %Y串
t1 = time.asctime(time.localtime(2000000000)) # 结构化时间 %a %b %d %H:%M:%S %Y串
print(t) # Tue Sep 4 16:04:17 2018
print(t1) # Wed May 18 11:33:20 2033
时间戳 --> %a %b %d %H:%M:%S %Y串
t = time.ctime()
t2 = time.ctime(2000000000)
print(t) # Tue Sep 4 16:06:32 2018
print(t2) # Wed May 18 11:33:20 2033
四、随机数模块
随机小数(一般用于科学计算)
random.random() 0-1之间的小数(0,1)
import random
r = random.random() # 0-1之间的小数
print(r)
print(round(r,2)) # 保留两位小数
'''
0.13465619587224942
0.13
'''
random.uniform(a,b) a-b之间的小数 (a,b)
r1 = random.uniform(10,100) # 10-100之间的小数
r2 = random.uniform(100,10) # 10-100之间的小数
print(r1)
print(r2)
'''
66.24475927171648
31.986449179748902
'''
随机整数
random.randint(a,b) a-b之间的整数 [a,b]
r1 = random.randint(5,10) # 5-10之间的整数 [5-10]
print(r1) # 5
random.randrange(a,b) a-b之间的整数[a,b)
r1 = random.randrange(1,100) # 1-100之间的整数 [1,100)
print(r1) # 88
random.randrange(a,b,c) a-b步长为c的整数 [a,b)
r1 = random.randrange(0,100,2) # 0-100之间的偶数的随机数,[0,100)
print(r1) # 52
列表中的随机元素
random.choice(list/tuple/range/str) 从列表总随机抽取一个元素
lis = ['a','b','c',1,2,3]
r1 = random.choice(lis) # 从列表中随机一个元素
print(r1) # 3
random.sample(list,n) 从列表中随机抽取n个元素,组成列表
lis = ['a','b','c',1,2,3]
r = random.sample(lis,2) # 从列表中随机2个元素组成列表
print(r) # ['a', 'c']
列表的乱序排列(在原列表的上修改)
random.shuffle(list) 在原列表的基础上打乱列表元素,节省内存
lis = ['a','b','c',1,2,3]
random.shuffle(lis) # 打乱列表的元素
print(lis) # [3, 2, 1, 'b', 'c', 'a']
验证码
import random
def verification_code(n=6,letter_flag = True):
code = ''
for i in range(n):
c = str(random.randint(0,9)) # 0-9整数的随机数
if letter_flag: # letter_flag随机字母
cap = chr(random.randint(65,90)) # A-Z的随机字母,通过chr转化为字母
low = chr(random.randint(97,122)) # a-z的随机字母,通过chr转化为字母
c = random.choice([c,cap,low])
code += c
return code
五、OS模块
__file__ 当前文件位置
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.system("bash command") 运行shell命令,直接显示
os.popen("bash command).read() 运行shell命令,获取执行结果
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd
os.path
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.path.getsize(path) 返回path的大小
stat 结构:
st_mode: inode 保护模式
st_ino: inode 节点号。
st_dev: inode 驻留的设备。
st_nlink: inode 的链接数。
st_uid: 所有者的用户ID。
st_gid: 所有者的组ID。
st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。
st_atime: 上次访问的时间。
st_mtime: 最后一次修改的时间。
st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是创建时间(详细信息参见平台的文档)。
os模块的属性
os.sep 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep 输出当前平台使用的行终止符,win下为"\r\n",Linux下为"\n"
os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
六、sys模块
sys.path 一个模块能否被导入,就看这个模块所在的目录在不在sys.path路径中,import某个模块会从头到尾取找某个模块,找到就返回
内置模块在python/lib,第三方模块在/venv/lib/site-pakcages
内置模块和第三方扩展模块都不需要处理,sys.path就可以直接调用
自定义模块的导入工作需要手动修改sys.path,当前文件夹的首个位置
sys.argv 执行py文件的时候传入的参数
sys.path 查看模块搜索路径 import 模块的时候从这个路径下来寻找
sys.modules 查看当前导入的模块和它的命名空间
sys.argv 命令行参数List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时exit(0)
sys.version 获取Python解释程序的版本信息
sys.maxint 最大的Int值
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
七、collection 模块
collection 根据基础数据类型做了一些扩展:
① Counter
② 有序字典
③ 默认字典
④ 可命名元组
⑤ 双端队列
Counter
Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。
from collections import Counter
c = Counter('abcabcde') # 可传入可迭代对象来创建(list、tuple、dict、str等)
print(c) # Counter({'a': 2, 'b': 2, 'c': 2, 'd': 1, 'e': 1})
print(c['z']) # 访问的键不存在,返回0
计数器的更新(增加和减少)
from collections import Counter
c = Counter('hello')
c.update('hello') # 计算器的更新:增加
print(c) # Counter({'l': 4, 'h': 2, 'e': 2, 'o': 2})
c.subtract('hello') # 计算器的更新:减少
print(c) # Counter({'l': 2, 'h': 1, 'e': 1, 'o': 1})
常用操作:
elements() # 返回一个迭代器。元素被重复了多少次,在该迭代器中就包含多少个该元素。元素排列无确定顺序,个数小于1的元素不被包含。
sum(c.values()) # 所有计数的总数
c.clear() # 重置Counter对象,注意不是删除
list(c) # 将c中的键转为列表
set(c) # 将c中的键转为set
dict(c) # 将c中的键值对转为字典
c.items() # 转为(elem, cnt)格式的列表
Counter(dict(list_of_pairs)) # 从(elem, cnt)格式的列表转换为Counter类对象
c.most_common()[:-n:-1] # 取出计数最少的n-1个元素
c += Counter() # 移除0和负值
del c['a'] # 删除键值对
OrderedDict 有序字典,python3.6版本以后的字典是有序的
from collections import OrderedDict
dic = OrderedDict([('a',1),('b',2)]) # OrderedDict 的创建
print(dic) # OrderedDict([('a', 1), ('b', 2)])
defaultdict 默认字典
defaultdict类的初始化函数接受一个类型作为参数,当所访问的键不存在的时候,可以实例化一个值作为默认值
from collections import defaultdict
func = lambda :'default'
l = defaultdict(func)
print(l['a']) # 不存在该键,会返回默认值
l['a'] = 1
print(l)
'''
default
defaultdict(<function <lambda> at 0x0000027577BE2E18>, {'a': 1})
namedtuple 可命名元组
语法:namedtuple(类名,[对象属性])
使用场景:元组的元素都有固定的意义,就用可命名元组,非常类似一个只有属性没有属性的类。
只有属性没有方法,当定义一个类,属性是不变的,没有方法,就可以使用可命名元组
特点:
a.元组的是不可变的,元素不能修改
b.元组要描述很多值,用户能直观地看到
c.和元组没有交集,不能通过索引访问,只能通过属性访问
d.一旦实例化就不能修改属性的值
from collections import namedtuple
today = namedtuple('Date_today',['year','month','day'])
d = today(2018,9,5)
print(d.year) # 2018
print(d.month) # 9
print(d.day) # 5
print(type(d)) # <class '__main__.Date_today'>
数据类型:队列
队列是一种数据类型,python里存在于模块,导入queue模块才能使用
队列的特性是先进先出,类似与买车票,队列能管理程序
所有的数据类型都能使用方法put()
import queue
q = queue.Queue()
queue.queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。
|queue.Queue|先进先出队列|
|queue.LifoQueue|后进先出队列|
|queue.PriorityQueue|优先级队列|
|queue.deque|双线队列|
get() # 将值放入队列中
put() # 将值从队列中取出
import queue
q = queue.Queue()
q.get(1) # 将一个值放入队列中
print(q.put(1)) # 将一个值从队列中取出
其他方法:
q.qsize() 返回队列的大小
q.empty() 如果队列为空,返回True,反之False
q.full() 如果队列满了,返回True,反之False
q.full 与 maxsize 大小对应
q.get([block[, timeout]]) 获取队列,timeout等待时间
q.get_nowait() 相当q.get(False)
非阻塞 q.put(item) 写入队列,timeout等待时间
q.put_nowait(item) 相当q.put(item, False)
q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号
q.join() 实际上意味着等到队列为空,再执行别的操作
deque 双端队列(效率比列表快)
列表insert插入操作是将所有的元素往后移,效率比较慢,所以列表不能使用insert的方法
双端队列的数据结构是链表
双端列表的操作方法跟列表相似
增加方法:
from collections import deque
d = deque()
d.append(1)
d.append(2)
d.appendleft(3)
print(d) # deque([3, 1, 2])
其他的方法:
clear(清空队列)
copy(浅拷贝)
count(返回指定元素的出现次数)
extend(从队列右边扩展一个列表的元素)
extendleft(从队列左边扩展一个列表的元素)
index(查找某个元素的索引位置)
insert(在指定位置插入元素)---> 效率比列表高1000倍
pop(获取最右边一个元素,并在队列中删除)
popleft(获取最左边一个元素,并在队列中删除)
remove(删除指定元素)
reverse(队列反转)
rotate(把右边元素放到左边)
八、hashllib 模块
这是一个内部有不止一种算法的模块。
由于数据的不安全性,为了保证用户的信息的绝对安全,所以的密码都不能以明文的形式存储,而是使用密文的形式存储,这时可使用这个模块。
模块里的算法都是摘要算法,该算法有特下特点:
① 算法不可逆,即密文不能反推明文
② 不同的字符串通过这个算法计算的密文总是不同的
③ 相同的算法,相同的字符串,获得的结果总是相同
④ 不同的语言,不同的环境都能通用
该模块应用场景:
① 登陆验证
② 文件的一致性校验
模块里最常用的算法:
① MD5算法
② sha算法
MD5 算法
步骤:
① 必须初始化对象
② update() 将字符串转化为密文,该方法接收的只能是bytes类型
③ 通过hexdigest() 方法获得结果
import hashlib
md5_obj = hashlib.md5() # 初始化对象
md5_obj.update('abcde'.encode('utf-8')) # 只能接收bytes类型,转化为密文
ret = md5_obj.hexdigest() # 获取转化后的密文
print(ret) # b56b4d92b40713acc5af89985d4b786
登陆验证
import hashlib
def login(user,pwd):
md5 = hashlib.md5()
md5.update(pwd) # 将传入的密码转化为密文
pwd = md5.hexdigest()
with open('userinfo',encoding='utf-8') as f:
for line in f:
username,password = line.strip().split(',')
if user == username and pwd == password:
return True
else:
return False
MD5算法的总结:
① 目前应用最广的字啊要算法,效率高,相对于SHA算法不复杂,如果只是传统的摘要不安全。
② 只要字符串不变,无论update多少次,结果都是一样的
③ 对象只能计算一次值,想再用MD5算法的方法,就需要重新实例化对象
④ 加密后的结果是一个32位16进制的字符串
import hashlib
md5_obj1 = hashlib.md5()
md5_obj1.update('mypassword'.encode('utf-8'))
ret1 = md5_obj1.hexdigest()
md5_obj2 = hashlib.md5()
md5_obj2.update('my'.encode('utf-8'))
md5_obj2.update('password'.encode('utf-8'))
ret2 = md5_obj2.hexdigest()
print(ret1 == ret2) # True
SHA1 算法
使用方式和MD5一致,加密后的结果是一个40位16进制的字符串。
SHA 还有其他算法,SHA 后面的数字越大算法越复杂,但是耗时越久,结果越长,同时安全性越高。
步骤:
① 必须初始化对象
② update() 将字符串转化为密文,该方法接收的只能是bytes类型
③ 通过hexdigest() 方法获得结果
import hashlib
sha_obj = hashlib.sha1()
sha_obj.update('abced'.encode('utf-8')) # 只接收bytes类型,转化为密文
ret = sha_obj.hexdigest() # 40位十六进制的字符串
print(ret) # bc748caecb1333dca5cecfdbc5b19833f5e1374a
传统的摘要算法存在的问题:撞库(通过密文表对照推测结果)
解决撞库的方案:加盐(加强安全性)
import hashlib
# 加盐
md5_obj1 = hashlib.md5('hello'.encode('utf-8')) # 加盐
md5_obj1.update('mypassword'.encode('utf-8'))
ret1 = md5_obj1.hexdigest()
# 传统摘要
md5_obj2 = hashlib.md5()
md5_obj2.update('mypassword'.encode('utf-8'))
ret2 = md5_obj2.hexdigest()
print(ret1,ret2)
# ret1 = 9402bc9c2e3e5cacced33cd10bc8f769
# ret2 = 34819d7beeabb9260a5c854bc85b3e44
但仍然不是绝对的安全,可能被恶意注册来获得密文表来对照推测结果和加盐方式,因此我们使用动态加盐
动态加盐即通过用户名在作为盐,一般情况用户名是唯一的,就算密码相同,密文也不一样。
# 动态加盐
import hashlib
def login(user,pwd):
md5 = hashlib.md5(user.encode('utf-8')) # 动态加盐
md5.update(pwd)
pwd = md5.hexdigest()
with open('userinfo',encoding='utf-8') as f:
for line in f:
username,password = line.strip().split(',')
if user == username and pwd == password:
return True
else:
return False
文件的一致性校验
给一个文件总的所有内容进行摘要算法,得到一个MD5值
大文件应该改以rb的形式来读,读出来的是bytes,不用编码。但是不能按行读,也不能一次性读出来,可以使用read(n)的方式来读取
import os,hashlib def get_md5(path,buffer = 1024): if os.path.exists(path): # 判断文件是否存在 path = os.path.abspath(path) # 转化为绝对路径 if os.path.isfile(path): # 判断是否文件 md5 = hashlib.md5() # 初始化md5对象 size = os.path.getsize(path) # 获得文件的大小 with open(path,'rb') as f: while size: r = f.read(buffer) # 一次读n个字节 size -= len(r) md5.update(r) # 转化为密文 return md5.hexdigest() # 返回MD5值
九、configparser 模块
configparser模块是用来解析ini配置文件的解析器
ini文件结构需要注意一下几点:
键值对可用=或者:进行分隔
section的名字是区分大小写的,而key的名字是不区分大小写的
键值对中头部和尾部的空白符会被去掉
值可以为多行
配置文件可以包含注释,注释以#或者;为前缀
注意:configparser有default_section的概念,默认为[DEFAULT]节,也就是之后的所有的section都有该默认section中的键值对
ConfigParser模块以ConfigParser类为例,其操作基本分为三类:1)初始化;2)读取配置;3)写入配置。
1. ConfigParser 初始化
使用ConfigParser 首选需要初始化实例,并读取配置文件:
cf = ConfigParser.ConfigParser() cf.read("配置文件名")
2. 基本的读取配置文件
-read(filename) 直接读取ini文件内容
-sections() 得到所有的section,并以列表的形式返回
-options(section) 得到该section的所有option
-items(section) 得到该section的所有键值对
-get(section,option) 得到section中option的值,返回为string类型
-getint(section,option) 得到section中option的值,返回为int类型,还有相应的getboolean()和getfloat() 函数。
3.基本的写入配置文件
-add_section(section) 添加一个新的section
-set( section, option, value) 对section中的option进行设置,需要调用write将内容写入配置文件。
十、logging 模块
日志的分级记录:
debug: 计算或工作的细节
info: 记录用户的增删改查操作
warning 警告操作
error 错误操作
critical 批判的错误,直接导致程序出错或退出
简单配置:
不能写中文,但不用创建对象
import logging
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(filename)s %(levelname)s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
'''
2018-09-06 17:24:11 exercise.py DEBUG debug message
2018-09-06 17:24:11 exercise.py INFO info message
2018-09-06 17:24:11 exercise.py WARNING warning message
2018-09-06 17:24:11 exercise.py ERROR error message
2018-09-06 17:24:11 exercise.py CRITICAL critical message
'''
了解一下 basicConfig 的参数都有哪些:
- filename:即日志输出的文件名,如果指定了这个信息之后,实际上会启用 FileHandler,而不再是 StreamHandler,这样日志信息便会输出到文件中了。
- filemode:这个是指定日志文件的写入方式,有两种形式,一种是 w,一种是 a,分别代表清除后写入和追加写入。 format:指定日志信息的输出格式,即上文示例所示的参数:
- %(levelno)s:打印日志级别的数值。
- %(levelname)s:打印日志级别的名称。
- %(pathname)s:打印当前执行程序的路径,其实就是sys.argv[0]。
- %(filename)s:打印当前执行程序名。
- %(funcName)s:打印日志的当前函数。
- %(lineno)d:打印日志的当前行号。
- %(asctime)s:打印日志的时间。
- %(thread)d:打印线程ID。
- %(threadName)s:打印线程名称。
- %(process)d:打印进程ID。
- %(processName)s:打印线程名称。
- %(module)s:打印模块名称。
- %(message)s:打印日志信息。
- datefmt:指定时间的输出格式。
- style:如果 format 参数指定了,这个参数就可以指定格式化时的占位符风格,如 %、{、$ 等。
- level:指定日志输出的类别,程序会输出大于等于此级别的信息。
- stream:在没有指定 filename 的时候会默认使用 StreamHandler,这时 stream 可以指定初始化的文件流。
- handlers:可以指定日志处理时所使用的 Handlers,必须是可迭代的。
对象的配置
① 可以写入多个文件,正常情况下只写一个
② 解决中文的问题
③ 同时向文件和屏幕输出内容
创建步骤:
① 先创建对象log对象,logger
② 创建一个控制文件输出的文件句柄
③ 创建控制屏幕输出的屏幕操作符
④ 创建一个格式
⑤ 文件句柄绑定一个格式
⑥ 屏幕操作符绑定一个格式
⑦ logger对象绑定文件句柄和屏幕操作符
import logging
logger = logging.getLogger() # 创建logging的对象
logger.setLevel(logging.DEBUG) # 设置告警等级DEBUG及以上告警
fh = logging.FileHandler('procedure.log',encoding='utf-8') # 创建文件输出的文件操作符
sh = logging.StreamHandler() # 创建控制屏幕输出的屏幕操作符
fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s',\
datefmt='%Y-%m-%d %H:%M:%S') # 创建格式
fh.setFormatter(fmt) # 文件操作符绑定格式
sh.setFormatter(fmt) # 屏幕操作符绑定格式
sh.setLevel(logging.ERROR) # 设置屏幕输出的告警等级
logger.addHandler(sh) # 对象绑定屏幕控制符
logger.addHandler(fh) # 对象绑定文件操作符
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
'''
2018-09-06 17:34:49 - root - ERROR - error message
2018-09-06 17:34:49 - root - CRITICAL - critical message
'''
参考文档:https://cuiqingcai.com/6080.html
https://www.cnblogs.com/yyds/p/6901864.html