1.json模块
1)json模块方法
①json.dumps()
②json.loads()
③json.dump()
④json.load()
2)json格式的限制
①json格式的key必须是字符串数据类型,如果是数字为key,那么dump之后会强行转成字符串数据类型
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json dic = {1:2,3:4} str_dic = json.dumps(dic) print(str_dic) new_dic = json.loads(str_dic) print(new_dic) 输出: {"1": 2, "3": 4} {'1': 2, '3': 4}
②json支持元组作为value,但是对元组做value的字典会把元组强制转化为列表
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json dic = {"abc":(1,2,3,4)} str_dic = json.dumps(dic) print(str_dic) new_dic = json.loads(str_dic) print(new_dic) 输出: {"abc": [1, 2, 3, 4]} {'abc': [1, 2, 3, 4]}
注:json不支持元组作为key,因为json只支持字符串数据类型作为json的key
③json格式中的字符串只能是双引号的,如果是单引号会报错
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json lst = ['123',"abc","27.58","ccc"] with open('json_test','w') as f: json.dump(lst,f) 文件内容: ["123", "abc", "27.58", "ccc"]
#读取文件内容
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json lst = ['123',"abc","27.58","ccc"] with open('json_test','w') as f: json.dump(lst,f) with open('json_test','r') as f: ret = json.load(f) print(ret) 输出: ['123', 'abc', '27.58', 'ccc']
注:若手动将json文件中的字符串改为单引号,读取文件内容就会报错
④可以多次的dump数据到文件中,但是不能将多次dump到文件中的内容load出来,因为是多种不同的数据类型了(即时dump的是多个列表)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json lst = ['123',"abc","27.58","ccc"] dic = {"a":"xyz","b":"jdk"} with open('json_test','w') as f: json.dump(lst,f) json.dump(dic,f) 文件内容: ["123", "abc", "27.58", "ccc"]{"b": "jdk", "a": "xyz"}
#dump多次后,load读取文件会出错
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json lst = ['123',"abc","27.58","ccc"] dic = {"a":"xyz","b":"jdk"} with open('json_test','w') as f: json.dump(lst,f) json.dump(dic,f) with open('json_test','r') as f: ret = json.load(f) print(ret) 报错: json.decoder.JSONDecodeError: Extra data: line 1 column 31 (char 30)
⑤若要想dump多个数据进入文件,可以使用dumps,
#先将dumps的每一行数据之后,加一个换行符
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json lst = ['123',"abc","27.58","ccc"] dic = {"a":"xyz","b":"jdk"} with open("json_test",'w') as f: str_lst = json.dumps(lst) str_dic = json.dumps(dic) f.write(str_lst+'\n') f.write(str_dic+'\n') 文件内容: ["123", "abc", "27.58", "ccc"] {"a": "xyz", "b": "jdk"}
#再将文件中的每一行内容loads出来
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json with open("json_test",'r') as f: for line in f: ret = json.loads(line) print(ret) 输出: ['123', 'abc', '27.58', 'ccc'] {'a': 'xyz', 'b': 'jdk'}
⑥对于中文格式的key,在文件默认存储的是bytes的类型,若想要保存在文件中也是中文,可以使用参数ensure_ascii = Fasle,(通过loads读取出来的还是中文)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json dic = {"name":"阿狸",'age':18,'sex':"女"} ret = json.dumps(dic) res = json.dumps(dic,ensure_ascii=False) print(ret) print(res) dic_new = json.loads(ret) print(dic_new) 输出: {"age": 18, "sex": "\u5973", "name": "\u963f\u72f8"} {"age": 18, "sex": "女", "name": "阿狸"} {'age': 18, 'name': '阿狸', 'sex': '女'}
3)json的其他参数
#为了用户看的方便,可以使用一些参数,但是会浪费存储空间
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json dic = {"name":['九尾妖狐','阿狸'],'age':18,'sex':"女"} ret = json.dumps(dic,sort_keys=True,indent=4,separators=(',',':'),ensure_ascii=False) print(ret) 输出: { "age":18, "name":[ "九尾妖狐", "阿狸" ], "sex":"女" }
注:set集合数据类型是直接不能序列化的,即json是不允许存储set集合的(set不能被dump以及dumps)
2.pickle模块
json处理的数据类型是有限的,此时可以使用pickle,但是pickle只有python语言可以识别
1)无论是什么数据类型,使用pickle进行dumps都不会报错,但是会转化为bytes类型,而且只支持转化为bytes类型(解码也不好使)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import pickle dic = {1:('a','b','c'),(1,2,3):"xyz"} pic_dit = pickle.dumps(dic) print(pic_dit) b'\x80\x03}q\x00(K\x01X\x01\x00\x00\x00aq\x01X\x01\x00\x00\x00bq\x02X\x01\x00\x00\x00cq\x03\x87q\x04K\x01K\x02K\x03\x87q\x05X\x03\x00\x00\x00xyzq\x06u.'
#使用pickle.loads()可以使原来的数据类型原封不动的恢复
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import pickle dic = {1:('a','b','c'),(1,2,3):"xyz"} pic_dit = pickle.dumps(dic) #bytes类型 new_dic = pickle.loads(pic_dit) print(new_dic) 输出: {1: ('a', 'b', 'c'), (1, 2, 3): 'xyz'}
注:只要通过pickle序列化后,就是bytes数据类型了,人类无法认识
使用场景:如果存一写数据,只是为了方便用户去看,就不要使用pickle序列化为bytes类型,而是保存为正常的文字状态;若是为了将一个数据类型存入文件,下次通过程序读出来的还是原来的数据类型,可以使用pickle
2)pickle支持几乎所有的对象
①pickle可以对类的对象进行序列化
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import pickle class Student: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex s1 = Student("阿狸",18,"女") print(pickle.dumps(s1)) 输出: b'\x80\x03c__main__\nStudent\nq\x00)\x81q\x01}q\x02(X\x03\x00\x00\x00ageq\x03K\x12X\x03\x00\x00\x00sexq\x04X\x03\x00\x00\x00\xe5\xa5\xb3q\x05X\x04\x00\x00\x00nameq\x06X\x06\x00\x00\x00\xe9\x98\xbf\xe7\x8b\xb8q\x07ub.'
#通过loads再将序列化的数据类型进行反序列化
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import pickle class Student: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex s1 = Student("阿狸",18,"女") ret = pickle.dumps(s1) reverse_ret = pickle.loads(ret) print(reverse_ret.name,reverse_ret.age,reverse_ret.sex) 输出: 阿狸 18 女
②以存入文件或从文件读取的方式对数据进行序列化或反序列化(使用pickle打开文件或读取文件必须是以wb或rb的方式,因为序列化后的数据类型为bytes)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Student: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex s1 = Student("阿狸",18,"女") import pickle with open("pickle_demo","wb") as f : pickle.dump(s1,f) with open("pickle_demo",'rb') as f: ret = pickle.load(f) print(ret.name,ret.age,ret.sex) 输出: 阿狸 18 女
注:对于如上程序要想正常的将文件中的内容反序列化出来,类必须存在,否则会报错(即对于对象的序列化需要这个对象对应的类在内存中)
应用场景:picke的dump和load非常适合游戏的读档和存档
3)通过pickle向文件dump多个值,并且load多个值出来
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
with open("pickle_demo","wb") as f: pickle.dump({"a":"1"},f) pickle.dump({"b":"2"},f) pickle.dump({"c":"3"},f) pickle.dump({"d":"4"},f) with open("pickle_demo","rb") as f: while True: try: print(pickle.load(f)) except EOFError: break 输出: {'a': '1'} {'b': '2'} {'c': '3'} {'d': '4'}
4)总结
①dump的结果是bytes,dump用的文件句柄需要以wb的形式打开,load用的文件句柄是rb模式
②pickle几乎支持所有对象的序列化
③对于对象的序列化需要这个对象对应的类在内存中
④对于多次dump和load的操作做了良好的处理
3.shelve模块(了解)
1)方法:shelve只提供一个方法open
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import shelve f = shelve.open("shelve.demo") #创建出三个文件 f['key'] = {'a': {1,2,3},'b':"xyz",'c':"阿狸"} f.close() f = shelve.open("shelve.demo") content = f['key'] f.close() print(content) #虽然关闭了文件,但是文件内容读取到了内存中 输出: {'a': {1, 2, 3}, 'c': '阿狸', 'b': 'xyz'}
2)shelve存到文件中的key,可以以字典的方式直接获取到,不需要像json或者pickle一样一个一个取出来,操作f,就类似操作字典一样
3)适用场景:如果写定了一个文件,改动的比较少,读文件的操作比较多,且大部分的读取都需要基于某个key获得某个value此时可以使用shelve
4)shelve在使用时会有很多限制或问题,尽量不用
总结:一般情况使用json; 如果需要频繁的保存某些状态,用pickle;如果频繁的取某些数据且需要某个key去获取value,可以使用shelve
4.hashlib模块
1)作用:hashlib模块提供了摘要算法,能够把字符串数据类型的变量转化为定长的密文的字符串,且字符串中每一个字符都是一个十六进制数字(字符串可转化为密文,但是密文不可转化为字符串,即不可逆)
2)摘要算法:对于同一个字符串,用相同的算法、相同的手段进行摘要,获得的值总是相同的
3)应用场景:登录的密文验证
#对于同一个字符串,不管这个字符串有多长,只要是相同的,无论在任何环境下,多少次执行,在任何语言中使用相同的算法、相同的手段得到的结果都是相同的;只要不是相同的算法/相同的手段得到的结果一定是不同的;只要不是相同的字符串、得到的结果一定不同
①md5算法
#md5得到的结果是一个32位的字符串,每个字符都是一个16进制
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import hashlib s = "zelasi001" md5_obj = hashlib.md5() #实例化一个对象 md5_obj.update(s.encode("utf-8")) #必须进行转码 ret = md5_obj.hexdigest() print(ret, type(ret)) 输出: 1e7ac35d19a1cab79d5afdf586705c73 <class 'str'>
②sha1算法的结果是一个40位的字符串,每个字符串都是一个16进制
#sha1算法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import hashlib s = "zelasi001" md5_obj = hashlib.sha1() #实例化一个对象 md5_obj.update(s.encode("utf-8")) #必须进行转码 ret = md5_obj.hexdigest() print(ret,type(ret)) 输出: 1e79f4ae7d434c9dc0142ee303a11826378bbc20 <class 'str'>
md5算法相比与sha1算法较简单,并且计算速度也较快(效率快);对于sha1算法,若计算的字符串较长,则计算速度慢,但是也更安全(安全不是因为算法本身的问题,而是用的人多,有人进行状况撞库)
注:可以使用加盐的方式,让md5方式变的安全
#盐可以是任意的字符串,只要代码不泄露,则就相对安全
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import hashlib s = "zelasi001" md5_obj = hashlib.md5("盐可以是任意字符串".encode("utf-8")) #加盐 md5_obj.update(s.encode("utf-8")) #必须进行转码 ret = md5_obj.hexdigest() print(ret,type(ret)) 输出: 49f0ed7a8df8ecd429f18754d609d647 <class 'str'>
注:即时以上述方式加盐也不安全,因为当用户密码一样,而同一个程序的盐又是相同的,那么加密后的字符串也是相同的,可以使用动态加盐的方式解决上述问题,即使用一个变量做为盐,如用户名
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import hashlib username = input("请输入用户名:") passwd = input("请输入密码:") md5_obj = hashlib.md5(username.encode("utf-8")) md5_obj.update(passwd.encode("utf-8")) ret = md5_obj.hexdigest() print(ret) 输出: 请输入用户名:ali 请输入密码:123456 c6cd1bcd66d1a3c10eee458e7eeab759
4)应用场景:文件的一致性校验
#只要文件内容不变,则md5结构不变
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import hashlib md5_obj = hashlib.md5() with open("t1.txt","rb") as f: md5_obj.update(f.read()) ret = md5_obj.hexdigest() print(ret) md5_obj = hashlib.md5() with open("t1_bak.txt","rb") as f: md5_obj.update(f.read()) ret = md5_obj.hexdigest() print(ret) 输出: aaa3f8e2e04da70a23312f477e8f18c4 aaa3f8e2e04da70a23312f477e8f18c4
#如果这个文件特别大,内存装不下,此时可以按照字节读,可以对一个字符串的某个阶段分别update,得出的结果一致
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import hashlib md5_obj = hashlib.md5() md5_obj.update("我爱北京天安门".encode()) print(md5_obj.hexdigest()) md5_obj = hashlib.md5() md5_obj.update("我爱".encode()) md5_obj.update("北京".encode()) md5_obj.update("天安门".encode()) print(md5_obj.hexdigest()) 输出: 4ae8f86d04e104db37c9d89736ec35f1 4ae8f86d04e104db37c9d89736ec35f1
5)对一个大文件进行校验
思路:写一个函数,计算文件的两个md5值,参数:文件1的路径,文件2的路径,默认参数=文件字节数(如1024),返回它们的一致性结果
5.configpaser模块
有一个固定格式的配置文件,用一个对应的模块去帮你做这个文件的字符串处理,即模块configpaser模块
1)该模块适用于配置文件的格式与windows ini文件类似,可以包含一个或多个节,每个节可以有多个参数(键=值)
注:每一个写在中括号中的值都是一个section,写在每个section下面的叫做option
2)所有的配置必须放置在一个分组中,分组名可以随便起,格式如下,只有写成类似的配置文件格式,才能被模块configpaser处理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
setting.ini [path] userinfog_path =E:\python\project\untitled\练习\userinfo userinfog_path =E:\python\project\untitled\练习\passwd
3)[DEFAULT]组为一个全局的组,其他组都能拿到[DEFAULT]的内容,其他组的option只包含在当前的组中
6.logging模块
1)功能:
①能做到日志格式的的规划
②操作的简化
③日志的分级管理
2)logging不能做的功能
①不能自动生成你要打印的内容
②要程序员自己在开发的时候定义好在那些地方需要打印,要打印的内容是什么,以及内容的级别
3)logging模块的使用
①普通配置型:简单的,可定制化差
②对象配置型:复杂的,可定制化强
4)日志级别
critical>error>warning>info>debug
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import logging logging.debug("Debug Message") #调试模式 logging.info("Info Message") #基础信息模块 logging.warning("Warning Message") #警告 logging.error("Error Message") #错误 logging.critical("Critical Message") #严重错误 输出: WARNING:root:Warning Message ERROR:root:Error Message CRITICAL:root:Critical Message 日志级别:用户:打印内容
注:logging模块默认只输出警告级别(warning)及以上的错误信息
#普通配置型(basicConfig)操作日志文件
①修改logging日志模块打印的默认级别
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import logging logging.basicConfig(level=logging.DEBUG) logging.debug("Debug Message") logging.info("Info Message") logging.warning("Warning Message") logging.error("Error Message") logging.critical("Critical Message") 输出: DEBUG:root:Debug Message INFO:root:Info Message WARNING:root:Warning Message ERROR:root:Error Message CRITICAL:root:Critical Message
②自定义logging模块日志输出的级别、格式、时间格式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import logging logging.basicConfig(level=logging.INFO, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S') logging.debug("Debug Message") logging.info("Info Message") logging.warning("Warning Message") logging.error("Error Message") logging.critical("Critical Message") 输出: Sat, 28 Nov 2020 16:14:45 基础代码练习.py[line:2798] INFO Info Message Sat, 28 Nov 2020 16:14:45 基础代码练习.py[line:2799] WARNING Warning Message Sat, 28 Nov 2020 16:14:45 基础代码练习.py[line:2800] ERROR Error Message Sat, 28 Nov 2020 16:14:45 基础代码练习.py[line:2801] CRITICAL Critical Message
③将打印的日志输出到文件(通过参数filename实现)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import logging logging.basicConfig(level=logging.INFO, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename="test.log") logging.debug("Debug Message") logging.info("Info Message") logging.warning("Warning Message") logging.error("Error Message") logging.critical("Critical Message")
注:普通配置型(basicConfig)不能将日志信息即输出到屏幕又输出到文件
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import logging logging.basicConfig(level=logging.INFO, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S') class Manager: def __init__(self,name): self.name = name def create_student(self): stu_name = input("学生姓名:") logging.info("%s create a student %s" %(self.name,stu_name)) ali = Manager("阿狸") ali.create_student() 输出: 学生姓名:劫 Sun, 29 Nov 2020 09:58:09 基础代码练习.py[line:2813] INFO 阿狸 create a student 劫
#logger对象的形式操作日志文件
①创建一个logger对象
②创建一个文件/屏幕管理操作符
③创建一个日志输出的格式
④文件管理/屏幕管理操作符绑定一个格式
⑤logger对象绑定文件/屏幕管理操作符(不绑定就无法往文件中输入)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import logging # 创建一个logger对象 logger = logging.getLogger() # 创建一个文件管理操作符 fh = logging.FileHandler('logger.log',encoding='utf-8') # 创建一个屏幕管理操作符 sh = logging.StreamHandler() # 创建一个日志输出的格式 format1 = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 文件管理操作符 绑定一个 格式 fh.setFormatter(format1) # 屏幕管理操作符 绑定一个 格式 sh.setFormatter(format1) logger.setLevel(logging.DEBUG) # logger对象 绑定 文件管理操作符 logger.addHandler(fh) # logger对象 绑定 屏幕管理操作符 logger.addHandler(sh) logger.debug('debug message') # 调试模式 logger.info('我的信息') # 基础信息 logger.warning('warning message') # 警告 logger.error('error message') # 错误 logger.critical('critical message')# 严重错误 输出: 2020-11-29 10:16:01,426 - root - DEBUG - debug message 2020-11-29 10:16:01,426 - root - INFO - 我的信息 2020-11-29 10:16:01,426 - root - WARNING - warning message 2020-11-29 10:16:01,427 - root - ERROR - error message 2020-11-29 10:16:01,427 - root - CRITICAL - critical message
7.异常处理
1)什么是异常,异常和错误的区别
XXXError为错误,一般是由于代码中比较明显的语法错误造成的,在编译代码就能检测出来
XXXIteration:异常,在执行代码的过程中就引发的异常
2)异常发生之后的效果
一但在程序中发生异常,程序就不再继续执行了;如果发生的异常对程序的后续执行没有影响,可以处理掉这个异常
4)如何看报错信息
IndexError为错误类型,整个具体的错误就是一个错误对象,整个错误是属于IndexError这一类的。
List index out of range为错误的具体提示(出现问题时,可利用该提示百度)
#若程序报很多错误,一般为从上往下数最后一个错误引起的;若是源码报错,可从报错的从下往上开始,找到第一行自己写的代码,这行代码就是出错的代码(一般为该行调用源码,导致源码出错了),源码是不会出错的。
5)最简单的异常处理
编译是不会报错,但是允许程序时出错
#当用户输入字母,或者超出列表数量的值时,就会出错,此时可以处理掉异常
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
l = ['登录','注册','退出'] for i in enumerate(l,1): print(i[0],i[1]) num = int(input("Num:")) print(l[num-1]) 输入: 1 登录 2 注册 3 退出 Num:a Traceback (most recent call last): File "E:/python/project/untitled/练习/基础代码练习.py", line 2845, in <module> num = int(input("Num:")) ValueError: invalid literal for int() with base 10: 'a'
#处理异常:先抓住异常,然后进行处理(报什么错,在except后就写什么错)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
l = ['登录','注册','退出'] for i in enumerate(l,1): print(i[0],i[1]) try: num = int(input("Num:")) print(l[n um-1]) except ValueError: print("请输入一个数字") 输出: 1 登录 2 注册 3 退出 Num:aa 请输入一个数字
注:但是对于如上的异常处理方式,一次只能处理一个异常,若要异常处理多个异常,可使用多分支异常处理
6)多分支异常处理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
l = ['登录','注册','退出'] for i in enumerate(l,1): print(i[0],i[1]) try: num = int(input("Num:")) print(l[num-1]) except ValueError: print("请输入一个数字") except IndexError: print("输入的数字无效") 输出: 1 登录 2 注册 3 退出 Num:5 输入的数字无效
②多分支异常的其他写法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
l = ['登录','注册','退出'] for i in enumerate(l,1): print(i[0],i[1]) try: num = int(input("Num:")) print(l[num-1]) except (ValueError,IndexError): print("Error") 输出: 1 登录 2 注册 3 退出 Num:5 Error
注:因为异常有很多种,使用如上方式处理异常,会显得程序很冗长,此时可以使用万能异常
7)万能异常
因为所有的类都继承了Exception类,所以可以直接使用Exception类处理异常
except Exception as 变量名: pass
变量名为错误的对象,可以使用如果只写except Exception无法确定具体是哪个地方出错了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
try : name except Exception as e : #e为变量名 print(type(e),e,e.__traceback__.tb_lineno) 输出: <class 'NameError'> name 'name' is not defined 2854
8)万能异常和多分支异常处理组合使用
对于可以预料到的异常,需要使用单分支异常去处理,对于无法预料的异常可以使用万能异常包住,保证其不出错
注:万能异常要放在所有多分支异常的最下面,except的条件是互斥的,即执行了最上面的except.则下面的就不执行了,如果把except Exception放在最上面,则就会把所有的异常在最上面就处理掉了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
try : name [][5] import a except NameError:pass except IndexError:pass except ImportError:pass except Exception as e :pass
9)异常处理其他机制
①
#如果try里面的代码顺利执行,就执行else语句
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
try: name = "阿狸" except NameError: print("Error") else: print("正常") 输出: 正常
②
#无论如何都会执行finally中的语句,即时在try语句中exit()了程序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
try: name = "阿狸" except NameError: print("Error") else: print("正常") exit() finally: print("执行finally中的语句") 输出: 正常 执行finally中的语句
#finally用法
如果打开一个文件,但是在打开文件的时候报错了,虽然报错了,但是文件是打开的,需要把文件关掉,即时文件没有处理异常,也可以使用finally的方式把文件关闭
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
try: f = open("file",'w') exit() finally: print("执行了finally") 输出: 执行了finally
注:程序的终端,函数的返回,都不会终端finally的执行,只要程序无论怎么样,都会执行,所以可在finally中做一些资源返回、回收的工作最合适
③主动抛异常(即主动写一个报错),但是借助的是python解释器的异常
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
try: num = int(input(">>>")) except Exception: print("在出现异常之后,做什么事情") raise #原封不动的输出try中抓到的异常 输出: >>>a 在出现异常之后,做什么事情 Traceback (most recent call last): File "E:/python/project/untitled/练习/基础代码练习.py", line 2887, in <module> num = int(input(">>>")) ValueError: invalid literal for int() with base 10: 'a'
10)自定义异常
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class CustomException(Exception): #自定义的异常类,必须基础Exception类 def __init__(self,msg): self.msg = msg raise CustomException("这是一个XXX错误,有XXX问题") #实例化类,传信息 输出: Traceback (most recent call last): File "E:/python/project/untitled/练习/基础代码练习.py", line 2896, in <module> raise CustomException("这是一个XXX错误,有XXX问题") __main__.CustomException: 这是一个XXX错误,有XXX问题
11)断言
如果某一段代码,必须满足某个必要条件才能执行,,且这个必要条件非常重要,关乎下面程序的执行,可以使用断言
①assert 布尔值
assert True:pass #如果条件为真,执行下面代码
assert False:pass #如果条件为假,不执行下面代码
②断言和if的区别是,不需要缩进
注:assert和rais一般在程序源码中出现
异常总结:能通过逻辑规避的错误因该用代码逻辑规避掉,应对对某一句或几句话进行处理;只有在程序最后的最后,为了增加用户体验,在外层添加一个大的异常处理;但是调试程序时,要把这个外层的异常去掉
8.双端队列
1)collections模块:提供了扩展数据类型(即数据类型的扩展模块)
2)队列:先进先出
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import queue q = queue.Queue() q.put('a') #往队列中放入值 q.put(1) q.put((1,2,3)) q.put({'k':"value"}) print(q) #打印的是一个内存地址,而获取不到数据 print(q.get()) #获取第一个放进去的顺序,get一次,队列中少一个值 print(q.qsize()) #查看队列的大小 输出: <queue.Queue object at 0x0000026CD3BCB668> a 3
适用场景:在排队做事情时,如用户批量访问时,先请求的先处理
3)双端队列:从两边都可取值,越先进去的值越在中间,而取值的时候是从两端往中间取值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from collections import deque dq = deque() dq.append(5) dq.append('xyz') dq.append((2,4,6)) dq.append({"k":"value"}) print(dq) #可以直接看到双端队列中的值 print(dq.pop()) print(dq) 输出: deque([5, 'xyz', (2, 4, 6), {'k': 'value'}]) {'k': 'value'} deque([5, 'xyz', (2, 4, 6)])
#其他用法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from collections import deque dq = deque() dq.append(5) dq.append('xyz') dq.append((2,4,6)) dq.append({"k":"value"}) dq.remove('xyz') #删除某个固定的值 print(dq) dq.insert(2,"阿狸") #在第二个位置插入一个值 print(dq) dq.appendleft("哈哈") #在最左边插入一个值 print(dq) 输出: deque([5, (2, 4, 6), {'k': 'value'}]) deque([5, (2, 4, 6), '阿狸', {'k': 'value'}]) deque(['哈哈', 5, (2, 4, 6), '阿狸', {'k': 'value'}])
注:双端队列的方法虽然和列表一致,但是在底层的数据结构不一样(双端队列和C语言链表一样);对于remove/insert这样的操作,用双端队列的平均效率比列表高,而在列表根据索引查看某个值的效率要高于双端队列