python之路20--之常用模块

模块

1、什么是模块

    常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。

    但其实import加载的模块分为四个通用类别: 

  1 使用python编写的代码(.py文件)

  2 已被编译为共享库或DLL的C或C++扩展

  3 包好一组模块的包

  4 使用C编写并链接到python解释器的内置模块

2、为何要使用python模块

        如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。

        随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用,

3、模块的导入

        模块的导入应该再程序最开始的地方,使用import 模块名字

1、导入模块
import time       #导入time模块

2、导入模块下的某一个功能
from collections import namedtuple          #只导入collections模块下的namedtuple功能

4、本文写道的基础常用模块说明

  • collections模块  -->  python中的扩展数据类型的模块
  • time模块  -->  时间模块
  • random模块  -->  随机数模块
  • os模块  -->  和系统打交道的模块
  • sys模块  -->  和python解释器打交道的模块
  • 序列化模块  -->  (json:和别的语言通信的序列化模块、pickle:python内部的序列化模块、shelve:python3新出的模块)
  • re模块  -->  正则表达式模块

一、collections模块

1、可命名元组
from collections import namedtuple           #表示从collections模块里调用namedtuple方法
Point = namedtuple('point',['x','y','z'])
p = Point(1,2,3)    #将1赋值给x、2赋值给y、3赋值给z
p2 = Point(5,6,7)   #将5赋值给x、将6赋值给y、7赋值给z
print(p.x)        #结果为:1
print(p.y)        #结果为:2
print(p.z)        #结果为:3
print(p2.x)       #结果为:5
print(p2.y)       #结果为:6
print(p2.z)       #结果为:7
print(p,p2)        #point(x=1, y=2, z=3) point(x=5, y=6, z=7)
2、显示扑克牌的花色和数字
from collections import namedtuple           #表示从collections模块里调用namedtuple方法
Card = namedtuple('card',['suits','number'])
c1 = Card('红桃',2)
print(c1)   #结果为:card(suits='红桃', number=2)
print(c1.suits,':',c1.number)     #结果为:红桃 : 2
扩展:队列
import queue
q = queue.Queue()      #创建队列
q.put(10)              #往队列里写入值
q.put(5)              #往队列里写入值
q.put(6)              #往队列里写入值
print(q.get())        #从队列里获取值,结果为:10
print(q.get())        #从队列里获取值,结果为:5
print(q.qsize())      #获取队列长度,取出两个值后队列长度为1
3、双端队列
from collections import deque
dq = deque([1,2])     #创建双端队列,此时队列为:[1,2]
dq.append('a')          #从后面放数据,此时队列为:[1,2,'a']
dq.appendleft('b')    #从前面放数据,此时队列为:['b',1,2,'a']
dq.insert(1,3)         #在dq队列下标是1的位置插入3,此时队列为:['b',3,1,2,'a']
print(dq.pop())         #从后面取数据        结果是:a
print(dq.popleft())     #从前面取数据        结果是:b
4、OrdereDict:有序字典
from collections import OrderedDict
od = OrderedDict([('a',1),('b',2),('c',3)])         #定义有序字典
print(od)    #OrdereDict的key是有序的,结果为:OrderedDict([('a', 1), ('b', 2), ('c', 3)])
print(od['a'])       #获取有序字典中a对应的值,结果为:1
for i in od:         #循环获取有序字典中的键
    print(i)     #结果为:a   b   c
5、defaultdict:设置默认值的字典
方法1:
from collections import defaultdict
d = defaultdict(lambda :5)       #定义一个默认value的字典,这里定义的默认value为(匿名函数的返回值是5),默认值必须是可以调用的类型,如:列表、字典、元组、匿名函数
print(d['k'])         #之前没有给d这个字典里写入键值,但是此时调用d这个字典下的k这个键,会打印出对应的值为:5

方法2:
def func():         #定义函数
    return 3
from collections import defaultdict
d = defaultdict(func)      #调用函数
print(d['k'])       #结果为3
6、Counter计数
from collections import Counter
c = Counter('abcdeabcdabcaba')       #会计算出字符串里出现的字符次数
print(c)           #结果为:Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})

二、time模块

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

(2)格式化的时间字符串(Format String): ‘1999-12-06’:给人看的

(3)结构化时间(struct_time)以元组的形式显示 :struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天等),计算用的

%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00=59)
%S 秒(00-59)
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化的月份名称
%B 本地完整的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区的名称
%% %号本身
 1、时间戳、字符串格式时间和结构化时间
import time
time.sleep(1)          #暂停一会,可以指定停多长时间(单位是秒)
print(time.time())            #从1970年到现在的时间戳(单位是秒),一时间戳的形式展示,结果为:1535600311.7133896
print(time.strftime("%Y-%m-%d %H:%M:%S"))    #结果为:年-月-日 时:分:秒   #字符串格式时间,%Y:year, %m:moth, %d:day, %X(时分秒的意思), %H:hour, %M:minute, %S:second
print(time.localtime())          #结构化显示时间(以元组的形式显示),结果为:time.struct_time(tm_year=2018, tm_mon=8, tm_mday=30, tm_hour=11, tm_min=38, tm_sec=31, tm_wday=3, tm_yday=242, tm_isdst=0)
2、单独获取结构化时间的某一个元素
import time
str_time = time.localtime()      #将结构化的时间定义变量,time.struct_time(tm_year=2018, tm_mon=8, tm_mday=30, tm_hour=11, tm_min=38, tm_sec=31, tm_wday=3, tm_yday=242, tm_isdst=0)
 print(str_time.tm_year) #获取结构化时间的年份,结果为:2018
3、时间之间的转换:时间戳和字符串格式的时间是不可以直接转换的,他们之间的转换需要通过结构化的时间来进行时间转换
1、时间戳和结构化时间的转换
t = time.time()                 #获取本地时间戳
print(time.localtime(t))       #将时间戳转化为序列化的时间
print(time.gmtime(t))          #将时间戳转化为格林威治的格式化时间(中国比格林威治的时间快八个小时)
print(time.mktime(time.localtime()))       #将序列化的时间转成时间戳

print(time.strptime('2018-09.06','%Y-%m.%d'))         #将字符串格式的时间转换为序列化的时间,语法:time.strptime('时间','时间格式')
print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(3000000000)))       #将时间戳转换为字符串的格式,语法:time.strftime('时间显示的格式',time.localtime(时间戳))


print(time.asctime())          #结果是:Sun Aug 26 15:52:00 2018
#将结构化时间转换为asctime时间print(time.asctime(time.localtime()))       #time.localtime:获取结构化时间并将结构化时间转换为asctime格式,结果为:Thu Aug 30 11:45:57 2018print(time.ctime())                        #显示ctime格式的时间,结果为:Thu Aug 30 11:45:57 2018print(time.ctime(3000000000))              #将时间戳转换为ctime的形式:结果为:Sat Jan 24 13:20:00 2065

三、random模块

1、随机小数
import random
print(random.random())       #返回大于0小于1的小数
print(random.uniform(1,3))      #返回大于1小于3的小数
2、随机整数
import random
print(random.randint(1,5))      #返回大于等于1且小于等于5之间的整数
print(random.randrange(1,10,2))      #返回大于等于1且小于10之间的奇数,步长是2
3、随机选择返回一个值
import random
print
(random.choice([1,'23',[4,5]])) #随机返回一个,1或‘23’或[4,5] print(random.sample([1,'23',[45]],2)) #返回列表元素任意2个组合
4、打乱列表后显示
import random
item = [1,3,5,7,9]
random.shuffle(item)
print(item)        #打乱列表的顺序后显示
5、随机验证码
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="".join([code,str(add)])
    return code
print(v_code())

四、sys模块

import sys
print(sys.platform)       #打印操作系统版本信息(多少位的可能不准)
print(sys.version)        #打印python解释器的版本信息
sys.exit()                #程序退出,可以指定返回结果,正确退出:sys.exit(0),错误退出:sys.exit(1)
print(sys.path)             #返回模块的搜索路径,初始化时
print(sys.argv)             #可以执行脚本时接收参数(再pycharm里执行看不出效果)

#接收参数脚本示例:该内容需要在系统里执行,执行命令:python script-name 参数1 参数2
ret = sys.argv
name = ret[1]
pwd = ret[2]
if name == 'ouyang' and pwd == '123':
    print("登陆成功...")
else:
    print("用户名或密码输入错误...")
    sys.exit()

五、os模块

os模块是与操作系统交互的一个接口

os.makedirs('dirname1/dirname2')    #可生成多层递归目录
os.removedirs('dirname1')    #若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')    #生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname')    #删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')    #列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove('filename')    #删除一个文件
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.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('/hello/','good/boy/','doiido')    #将多个路径组合后返回,第一个绝对路径之前的参数将被忽略,打印结果为:/hello/good/boy/doiido
os.path.getatime('path')    #返回path所指向的文件或者目录的最后访问时间
os.path.getmtime('path')   #返回path所指向的文件或者目录的最后修改时间
os.path.getsize('path')     #返回path的大小

5.1、os.stat('path/filename')  获取文件/目录信息 的结构说明

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'

六、序列化模块

                               序列化和反序列化需要在相同的环境下进行

python里的三个序列化的模块:

  #json  --   (五星):通用的序列化格式,基本上所有的开发语言都用的序列化格式(只有很少的一部分数据类型能够通过json转化成字符串)
#pickle -- (四星):python独有的序列化类型,所有python中的数据类型都可以转化成字符串形式,pickle序列化的内容只有python能理解,部分反序列化依赖python代码。
#shelve -- (三星):python3的新模块,序列化句柄(使用句柄直接操作,非常方便)

什么是序列化:

  #从数据类型 --> 到字符串的过程叫作序列化(为了方便存储和网络传输)
#从字符串 --> 到数据类型的过程叫作反序列化

5.1、json序列化 

1、dumps序列化和loads反序列化

    dumps和loads是再内存里对数据类型进行序列化,然后显示出来!!

dic = {"k1":"v1"}       #定义字典
print(type(dic),dic)     #打印字典类型,结果为:<class 'dict'> {'k1': 'v1'}
import json                #导入json模块
str_d = json.dumps(dic)        #将字典类型序列化为字符串类型
print(type(str_d),str_d)         #打印序列化后的类型,结果为:<class 'str'> {"k1": "v1"}
dic_d = json.loads(str_d)      #将字符串类型反序列化为原类型
print(type(dic_d),dic_d)        #打印反序列化后的类型,及反序列化后的结果,结果为:<class 'dict'> {'k1': 'v1'}

注:json支持序列化的类型有:数字、字符串、列表、元组(元组是序列化成列表,反序列化也是反序列化成列表)

2、dump和load方法

    dump和load是将序列化的类型写入到文件里,然后从文件里读取出来进行反序列化,json的load不可以多次load。

import json
dic = {1:'a',2:'b'}
f = open('file',mode='w',encoding='utf-8')
json.dump(dic,f)      #将dic的内容序列为字符串然后写入到f对应的文件中
f.close()

f = open("file",mode='r',encoding='utf-8')
res = json.load(f)     #从文件句柄f里面读取内容并序列化为字典,
print(type(res),res)   #结果为:<class 'dict'> {'1': 'a', '2': 'b'}
f.close()
2.1、当遇到中文时使用dump将序列化后的值写入到文件里时,查看文件出现bytes类型的乱码的解决办法(不影响load反序列化)
import json
dic = {1:'中国',2:'牛逼'}
f = open('file',mode='w',encoding='utf-8')
json.dump(dic,f,ensure_ascii=False)      #将dic的内容序列为字符串并写入到f对应的文件中,此时查看文件中的内容出现乱码:{"1": "\u4e2d\u56fd", "2": "\u725b\u903c"},解决这个问题需要在dump时加上ensure_ascii=False参数即可解决
f.close()

f = open("file",mode='r',encoding='utf-8')
res = json.load(f)     #从文件句柄f里面读取内容并序列化为字典,
print(type(res),res)   #结果为:<class 'dict'> {'2': '牛逼', '1': '中国'}
f.close()
问题:dump和load可不可以按行写入到文件里,然后按行读取?

答:不可以,具体看如下代码

import json
dic = {1:'中国',2:'牛逼'}
f = open('file',mode='w',encoding='utf-8')
f1 = open('file',mode='w',encoding='utf-8')
json.dump(dic,f,ensure_ascii=False)       #写入第一次
json.dump(dic,f1,ensure_ascii=False)     #写入第二次
f.close()

f = open("file",mode='r',encoding='utf-8')
res = json.load(f)     #读取第一次
res1 = json.load(f1)   #读取第二次
print(type(res),res)
print(type(res1),res1)
f.close()

执行报错如下:io.UnsupportedOperation: not readable    说不可读

现在有需求需要实现序列化后的数据按行写入文件然后在按行读取出来如何实现?看下面代码:

import json 
li = [{'k':'aaa'},{'k2':'bbb'},{'k3':'ccc'}]        #需要写入的数据
f = open('file',mode='w',encoding='utf-8')      #打开文件
for i in li:
    str_dic = json.dumps(i)       #序列化需要写入的数据,
    f.write(str_dic+ '\n')        #将序列化后的内容按行写入文件,在每一行后+换行符
f.close()
f = open('file',mode='r',encoding='utf-8')       #打开文件
for line in f:
    file_line = line.strip()        #读取文件并去除换行符
    print(json.loads(file_line))     #读取结果
f.close()
#结果为:
{'k': 'aaa'}
{'k2': 'bbb'}
{'k3': 'ccc'}

这样就实现了序列化后的数据按行写入到文件,然后再按行读取的功能了!!

3、json的一些其他参数说明

Skipkeys:默认值是False,如果dict的keys内的数据不是python的基本类型(str,unicode,int,long,float,bool,None),设置为False时,就会报TypeError的错误。此时设置成True,则会跳过这类key
ensure_ascii:当它为True的时候,所有非ASCII码字符显示为\uXXXX序列,只需在dump时将ensure_ascii设置为False即可,此时存入json的中文即可正常显示。)
indent:应该是一个非负的整型,如果是0就是顶格分行显示,如果为空就是一行最紧凑显示,否则会换行且按照indent的数值显示前面的空白分行显示,这样打印出来的json数据也叫pretty-printed json
separators:分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(‘,’,’:’);这表示dictionary内keys之间用“,”隔开,而KEY和value之间用“:”隔开。
sort_keys:将数据根据keys的值进行排序。

3.1、json的序列化输出
1、代码
import json
data = {'username':['张三','李四'],'uxuan':'diyi','age':16}
json_dic2 = json.dumps(data,sort_keys=True,indent=2,separators=(',',':'),ensure_ascii=False)
print(json_dic2)

2、输出结果如下:
{
  "age":16,
  "username":[
    "张三",
    "李四"
  ],
  "uxuan":"diyi"
}

5.2、pickle模块

        pickle为python自带的序列化工具,支对python有效,别的语言不识别,

        pickle可以序列化python的所有数据类型,将数据类型序列化为bytes类型,

        同样有dumps、loads和dump、load两种序列化和反序列化的方法,dump和load的时候文件是用wb和rb的方式打开的。

 

1、pickle的dumps和loads方法
import pickle
dic = {'k1':'v1','k2':'v2','k3':'v3'}     #定义字典
str_dic = pickle.dumps(dic)          #实现序列化(序列化为bytes类型)
print(str_dic)         #返回一串bytes类型的内容

dic2 = pickle.loads(str_dic)     #反序列化
print(dic2)        #返回字典
2、pickle的dump和load方法
import time
import pickle
str_time = time.localtime(100000)     #获取序列化的时间格式
print(str_time)         #结果为:time.struct_time(tm_year=1970, tm_mon=1, tm_mday=2, tm_hour=11, tm_min=46, tm_sec=40, tm_wday=4, tm_yday=2, tm_isdst=0)
f = open('pickle_file',mode='wb')     #以bytes类型写的方式打开文件
pickle.dump(str_time,f)     #将以上结果以bytes的形式写入文件中
f.close()

f = open('pickle_file',mode='rb')      #以bytes类型读的方式打开文件
str_time2 = pickle.load(f)          #从文件中读取内容并反序列化
print(str_time2.tm_year)            #结果为1970
注:pickle对文件的操作都需要加b,因为pickle是序列化为bytes类型,pickle支持分次从文件里load内容并进行反序列化

5.3、shelve模块

        shelve模块是python3新出的序列化模块,shelve模块有个open方法获取一个文件的句柄,然后对文件句柄的直接操作,(不过有个小问题)

1、shelve模块使用方法

import shelve
f = shelve.open("shelve_file")       #用shelve模块自带的open方式打开文件
f["key"] = {'int':10,'float':9.5,'string':'sample data'}     #直接对文件句柄操作新增key及对应的值,就可以存入数据
f.close()

f1 = shelve.open('shelve_file')     #用shelve模块自带的open方式打开文件
existing = f1['key']    #获取数据的时候也只需要直接用key获取即可,但是如果key不存在会报错 
f1.close() 
print(existing)      #结果为:{'string': 'sample data', 'float': 9.5, 'int': 10}

2、shelve模块的小问题(以只读的方式打开文件还可以直接对文件进行修改)

import shelve
f = shelve.open('shelve_file',flag='r')        #以只读的方式打开文件
existing = f['key']
print(existing)        #结果是:{'string': 'sample data', 'int': 10, 'float': 9.5}
f['key'] = 10   #修改键对应的值
print(f['key'])    #修改后的结果为:10
f.close()

 七、hashlib模块

  • hashhlib:提供摘要算法的模块(作摘要计算的,把字节类型的内容进行摘要处理【加密】)(摘要算法不是一个算法,而是一堆算法),不管算法多么不同,摘要的功能始终不变,
  • 摘要算法:即将明文密码加密的过程,同一个字符串使用相同的算法得到的摘要值始终是一样的,使用不同算法对相同字符串进行摘要,得到的值应该不同,不管用什么算法,hashlib的方式永远不变
  • sha算法,随着算法复杂程度的增加,我摘要的时间成本和空间成本都会增加
  • 摘要算法用处:密码的密文存储、文件一致性验证(检查下载的文件和远程服务器上的文件是否一致,检查两个机器上的文件是否一样等)、
  • 文件的一致性校验:在文件的一致性校验中,算法不需要加盐
  • 正常算法、加盐算法、动态加盐算法等

7.1、使用hashlib的md5算法将一串字符串加密

import hashlib        #导入hashlib模块
md5 = hashlib.md5()      #使用hashlib的md5算法
md5.update(b'budaozhe')     #加密的字符串,必须转换为bytes类型
print(md5.hexdigest())      #结果为:13b4e2ebaaad153c71ef56b20d767cc2

7.2、使用hashlib模块密文登陆密码密码验证用法

import hashlib
username = input("UserName:")       #输入用户名
password = input("Password:")         #输入密码
with open('userinfo', mode='r', encoding='utf-8') as f:    #读取文件
    for line in f:
        user, passwd, role = line.split("|")     #以|为分割,获取用户名,密码,角色
        md5 = hashlib.md5()     #使用md5算法
        md5.update(bytes(password, encoding='utf-8'))    #加密密码
        md5_pwd = md5.hexdigest()    #加密结果
        if username == user and passwd == md5_pwd:     #判断:用户输入姓名是否等于文件中的姓名 and 文件中的密码是否等于用户输入的密码然后加密的结果
            print('登陆成功')      #是则执行这里
        print("用户名或密码输入错误")        #不是则执行这里

7.2、hashlib给算法加盐

import hashlib
md5 = hashlib.md5(bytes('',encoding='utf-8'))       #md5算法加盐
#md5 = hashlib.md5()       #正常使用md5算法
md5.update(b'budaozhe.co')     #加密的字符串
print(md5.hexdigest())       #结果为:251d5512257029fbf03a4377067b37e0

7.3、hashlib给算法动态加盐

    用户登录时输入用户名和密码,使用用户名的一部分或者直接使用整个用户名作为盐(不建议使用整个用户名,会被猜出来)
import hashlib
md5 = hashlib.md5(bytes('',encoding='utf-8')+b'salt')       #md5算法加盐
# md5 = hashlib.md5()       #正常使用md5算法
md5.update(b'budaozhe.co')     #加密的内容
print(md5.hexdigest())       #结果为:842621798592eddd3d482894615bdb98 ,发现跟上面的结果一样了

八、configparser模块,生成配置文件的模块

8.1、想要生成一个如下类型的配置文件

[DEFAULT]
forwardx11 = yes
compressionlevel = 9
serveraliveinterval = 45
compression = yes

[bitbucket.org]
user = hg

[topsecret.server.com]
host port = 50022
forwardx11 = no

8.1.1、通过configparser实现

import configparser       #导入configparser模块
config = configparser.ConfigParser()     #实例化一个config对象
config["DEFAULT"] = {'ServerAliveInterval': '45',     #语法:对象['组'] = {'键':'值'}
                      'Compression': 'yes',
                     'CompressionLevel': '9',
                     'ForwardX11':'yes'
                     }

config['bitbucket.org'] = {'User':'hg'}   #语法:对象['组'] = {'键':'值'}
config['topsecret.server.com'] = {'Host Port':'50022','ForwardX11':'no'}    #语法:对象['组'] = {'键':'值'}
with open('example.ini', 'w') as configfile:   #以写的方式打开一个文件
   config.write(configfile)       #对象.写方法(文件名):实现写入到文件中

8.1.2、通过configparser实现查找配置文件中的内容

import configparser
config = configparser.ConfigParser()      #实例化


print(config.sections()) # 结果为: [] 没有指定操作的文件名默认返回空列表
config.read('example.ini') #对象.读取('目标文件')

print(config.sections()) # ['bitbucket.org', 'topsecret.server.com'],显示组,默认不显示default

print('bytebong.com' in config) # False #判断这个组是不是再这个配置文件里,是则返回True、不是则返回False

print('bitbucket.org' in config) # True #判断这个组是不是再这个配置文件里,是则返回True、不是则返回False

print(config['bitbucket.org']["user"]) # hg #获取文件中的['bitbucket.org']组中的["user"]变量对应的值

print(config['DEFAULT']['Compression']) #yes 获取文件中['DEFAULT']组下的['Compression']变量对应的值

print(config['topsecret.server.com']['ForwardX11']) #no 获取['topsecret.server.com']组下的['ForwardX11']变量的值

print(config['bitbucket.org']) #<Section: bitbucket.org> 打印组名(也叫节名)

for key in config['bitbucket.org']: # 注意,有default会默认default打印的键 循环获取['bitbucket.org']组下的变量,获取完了['bitbucket.org']组下的变量后默认会打印default组下的所有变量,以字符串的形式返回 print(key)

print(config.options('bitbucket.org')) # 同for循环,找到'bitbucket.org'下所有键,获取完后也会打印default组下的所有键,以列表的形式返回

print(config.items('bitbucket.org')) #找到'bitbucket.org'下所有键值对

print(config.get('bitbucket.org','compression')) # yes get方法Section下的key对应的value

8.1.3、通过configpraser修改配置文件中的内容

import configparser
config = configparser.ConfigParser()     #实例化
config.read('example.ini')     #读文件

config.add_section('yuan')     #增加一个[net]组

config.remove_section('bitbucket.org')      #删除[bitbucket.org]组

config.remove_option('topsecret.server.com',"forwardx11")        #删除[topsecret.server.com]组下的forwardx11配置项


config.set('topsecret.server.com','k1','11111')     #在[topsecret.server.com]组里增加k1键,值为11111

config.set('yuan','k2','22222')      #在[yuan]这个组里增加以一个k2键,值为22222

f = open('new2.ini', "w")    #打开文件
config.write(f)       #写进文件中
f.close()    #关闭文件

九、logging模块:日志模块

        日志用来记录用户的行为 或者 代码的执行过程 或者 排错的时候 或者 严重的错误

日志的五种级别:

  • debug: #低级别 #排错信息
  • info: #正常的信息
  • warning: #警告信息
  • error: #错误信息
  • critical: #高级别。严重错误信息

日志的两种配置方式:

  • basicconfig:配置简单 能做的事相对少,中文会出现乱码问题,不能同时往文件里和屏幕上双输出
  • 配置log对象:配置稍微有点复杂,能做的事情相对多,支持中文,支持双输出

9.1、日志输出

import logging
logging.debug('debug message')     #低级别    #排错信息,默认不输出
logging.info('info message')      #正常的信息   #默认不输出
logging.warning('warning message')     #警告信息 ,结果为:WARNING:root:warning message
logging.error('error message')      #错误信息,结果为:ERROR:root:error message
logging.critical('critical message')   #高级别。严重错误信息,结果为:CRITICAL:root:critical message

9.2、配置basicconfig日志

import logging
logging.basicConfig(level=logging.INFO,           #level:配置日志级别(这里执行的是INFO以上的级别都打印),指定的日志级别以上的日志都打印,#配置日志格式
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S',
                    filename='test.log',      #往文件里输出,文件名
                    filemode='w')     #以写的方式打开文件
logging.basicConfig(level=logging.INFO,           #level:配置日志级别,指定的日志级别以上的日志都打印
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S')      #往屏幕上输出
try:       #匹配日志
    int(input('num:'))     #用户输入强转int类型
except ValueError:      #配置ValueError错误并将错误写入到日志
    logging.error(':input "key" ERROR')      #结果为:Tue, 16 Oct 2018 22:20:29 ����ģ��.py[line:183] ERROR ��input "key" ERROR ,这里有中文乱码,所以说basicconfig的日志模式有局限性

9.3、配置log对象格式的日志

import logging
logger = logging.getLogger()     #实例化
fh = logging.FileHandler('log.log',encoding='utf-8')      #指定日志输出的文件
sh = logging.StreamHandler()        #指定日志输出到屏幕
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')     #日志格式
formatter2 = logging.Formatter('%(asctime)s %(name)s %(levelname)s : %(message)s')     #日志格式
#文件操作符和日志格式关联(输出目的地和日志格式关联)
fh.setFormatter(formatter)
sh.setFormatter(formatter2)
#logger对象和文件操作关联(日志格式和输出地点关联)
logger.addHandler(fh)
logger.addHandler(sh)
logging.debug('debug message')     #低级别,排错信息(无输出)
logging.info('info message')      #正常的信息(无输出)
logging.warning('warning message')     #警告信息,结果为:2018-10-16 22:28:05,196 root WARNING : warning message
logging.error('error message')      #错误信息,结果为:2018-10-16 22:28:05,196 root ERROR : error message
logging.critical('critical message')   #高级别。严重错误信息,结果为:2018-10-16 22:28:05,197 root CRITICAL : critical message
try:       #匹配日志
    int(input('num:'))     #输入类型强转为int类型
except ValueError:      #配置ValueError错误并将错误写入到日志
    logging.error('input "key" ERROR')      #日志指定输出到屏幕

 

posted @ 2018-08-30 11:33  欧-阳  阅读(164)  评论(0)    收藏  举报