异常
异常也是一个对象
1. 异常的目的:
提高程序的容错性
容错性不能太高也不能太低
open('hehe.txt')
# FileNotFoundError: [Errno 2] No such file or directory: 'hehe.txt'
- 常见的异常
1. TypeError:类型异常,注释清楚变量的类型
2. ValueError:值异常
3. SyntaxError:语法错误
4. IndexError:索引错误
5. KeyError:键异常
6. AttributeError:属性错误、方法错误
7. ModuleNotFoundError:导包错误
8. ZeroDivisionError:除数为零
9. NameError:命名错误
10. IndentationError:缩进错误
11. KeyboardInterrupt:键盘输入终止异常
12. UnboundLocalError:变量区域错误:闭包
13. RecursionError:递归深度错误
- 异常处理
异常出现了怎么办:改代码,让异常没有
1. try-except
try:
可能出现异常的代码
except:
处理异常的方法
try:
可能出现异常的代码
except 异常类型 as 变量:
处理异常的方法
变量存储的是错误信息(异常信息)
流程:
try结构中如果出现异常,则执行except中的代码
注意:
1. 变量可以省略,(初学者)最好不要省略,在公司开发中,一般会省略
2. 如果try块中没有出现异常,则直接执行try中的代码,执行完毕以后跳出异常控制模块,不执行except
3. 如果try中出现异常
a. 如果except声明了指定的异常类型,则执行except中的代码
b. 如果except没有声明出现的的异常类型,则依然会报错
c. try中出现了异常,则异常代码以后的所有代码都不执行,直接去执行except中的代码
4. except里面的异常类型可以省略,表示捕获所有异常
最好不要省略:不知道错误类型,可读性就不太好
5. try-except结构中,可以有多个except块,目的:尽可能捕捉更多的错误
6. 在执行过程中,同一级中,只会执行一个except
2. try-except-finally
try:
可能出现异常的代码
except:
处理异常的代码
finally:
无论如何都要执行的代码
finally的用处:
一般用于释放资源(或者用于无论如何都应该执行的代码)
3. 嵌套
可以在任何块内嵌套try-except或者try-except-finally
# with open('1.txt',mode='w',encoding='utf-8') as w:
# w.write('abc')
#
#
#
# w.write('cde')
user = '用户'
if user == '用户':
try:
username = int(input('请输入用户名:'))
try:
username + 'abc'
except:
print('对不起,是我代码写错了')
except RecursionError as r:
print(r)
print('你丫有病吧')
except ValueError as b:
print('你丫有病吧')
print(b)
finally:
print('请充值')
else:
print('滚蛋')
#
# print('abc')
# print('你好')
0
# a = open('1.txt')
# a.write('abc')
# except:
# print('出错了')
# finally:
# a.close()
#
# print(a.closed)
自定义异常
- raise语句
主动抛出一个异常
a = input('雷麟是否英俊?')
if a == '是':
print('恭喜你答对了')
else:
raise ValueError
- 自定义异常
1. 自己定义异常类
2. 必须间接的或者直接的继承Exception类
Exception类:是所有异常的父类
3. raise 自定义异常类() 表示当前需要创建的异常类的对象
class 有眼无珠(Exception): passa = input('雷麟是否英俊?')if a == '是': print('恭喜你答对了')else: raise 有眼无珠()
print('xxx我爱你')
进程和线程
和并发有关企业级项目: 1. 安全问题 2. 并发问题 a.并发 b.高并发
邮箱: 1. 不要用QQ邮箱 1. QQ邮箱的垃圾邮件处理机制极其变态 2. 在某些情况下,QQ邮箱发送的时候会携带昵称 3. 首位必须是字母 4. 程序员:gmail(可以直接登录github) 申请gmail需要科学上网
- 任务调度
1. 操作系统,采用时间片轮转的抢占调度模式 QQ/微信/微博/腾讯会议 时间片:是操作系统分配出来的一小段执行时间 轮转:轮转的给出时间片,陆续给出时间片 抢占式:多个任务之间抢占时间片,抢到时间片的任务先运行,没抢到时间片的任务,则等待下一次争抢(等待的过程,该任务不执行)2. 为了防止某些进程一直占用时间片,任务执行了一段时间(阈值)以后,强制的暂停去执行下一个任务 当时间片使用完毕的时候,任务开始暂停3. CPU的计算速度快,分配时间片的时间无限接近于0,分配时间片时人类的感官体验其实是同步执行的.宏观并行/微观串行
- 进程
CPU:负责计算OS:管理任务/调度任务/资源分配1. 进程是一个具有独立功能的程序2. 是在一个数据集合上的一次动态的执行过程3. 是操作系统进行资源分配的独立单位4. 是应用程序运行的载体进程:是一个抽象的概念,没有统一的标准定义进程,进程结构: 1. 程序:描述进程所要完成的功能 2. 数据集合:是程序在执行时所需要的数据的工作区 3. 程序控制块:包含进程的描述信息和控制信息,是进程存在的唯一标志进程的特点: 1. 动态性 2. 并发性 3. 独立性 4. 结构性
- 线程
早期没有线程的概念,只有进程;只有一个进程不满足一个程序中多种业务的并行,所以出现了线程1. 是一个轻量级的进程 重:携带的资源,消耗的资源都很大 轻:携带的资源,消耗的资源较小2. 线程时程序执行的最小单位,是资源分配的最小单位3. 一个进程,由一到多个线程组成,线程是一个程序中不同功能的执行路线 QQ:聊天/语音/视频4. 进程之间互相独立,资源不共享;线程之间共享资源 脏读 python禁止了多线程5. 线程的调度比进程要快的多6. 线程的结构: 1. 线程ID ps -ef | grep 2. 指令指针 3. 寄存器 4. 堆栈
def movie(name,n): for i in range(n): print('看电影:%s'%name)def music(name,n): for i in range(n): print('听音乐:%s'%name)if __name__ == '__main__': movie('失控玩家',10) music('惊雷',10)# 有且只有一个流程,这个流程就是主线程---单线程:按照顺序执行代码(串行)\# 任何程序都至少要有一个线程(需要分配资源)
threading模块
1. threading模块用于创建线程2. 创建线程:使用Thread类的构造方法 threading.Thread def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None): group:分组 target:目标 name:名称/描述 args:可变长参数 kwargs:字典 daemon:守护进程
import threadingfrom threading import Threadclass Music(threading.Thread): def __init__(self,name,n): super().__init__() self.name=name self.n = n def run(self): for i in range(self.n): print('听音乐:%s'%self.name)class Movie(threading.Thread): def __init__(self, name, n): super().__init__() self.name = name self.n = n def run(self): for i in range(self.n): print('看电影:%s' % self.name)if __name__ == '__main__': music = Music('惊雷',30) movie = Movie('罗马假日',30) music.start() movie.start()
import threadingdef movie(name,n): for i in range(n): print('看电影:%s'%name)def music (name,n): for i in range(n): print('听音乐:%s'%name)if __name__ == '__main__': movie = threading.Thread(target=movie,args=('失控玩家',10)) music = threading.Thread(target=music,args=('童年',10)) movie.start() music.start()
- 守护进程
1. 直到死之前都一直存在2. python的垃圾处理机制是最典型的一个守护线程
- 线程的一生
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cfmfpliC-1644506874991)(day22-异常.assets/线程的一生.png)]
GIL锁
全局解释锁:Global Interpreter Lock锁:数据安全性问题 保证在同一时间,只有一个线程可以访问指定的对象,保证数据的安全1. GIL是C语言的锁,也是CPython中的锁 Cpython:用C语言实现的python,为了解决数据不安全的问题,偷来了一把锁,锁线程2. GIL作用 1. 保护数据安全 2. 控制线程数数量,节约成本,限制了速度 一个核是两个线程,GIL锁限制了核,无论有多少个核,只能用一个核3. 如果要执行线程,抢占GIL锁标记,有锁标记的才可以运行,但是锁标记轮转的时间间隔过短,python中的多线程实际上是单线程的快速切换 宏观并行.微观串行4. GIL锁几乎将多核CPU限制为了单核CPU
多进程模块:multiprocessing
multiprocessing:多进程1. 该模块用于替代threading模块 CPU密集型程序,需要解决GIL锁导致的性能降低的问题2. multiprocessing模块和treading差不多3. 该模块是多进程模块: 1. 多进程的资源相互独立/不共享 2. 多线程资源共享 资源密集型:需要多次频繁访问同样的资源CPU密集型:多进程
- POOL
池:装东西的/存东西的进程池:进程1. 作用:提供指定数量的进程,用于调用 1. 当有新的进程提交到POOL中的时候,如果池没满,则在池中进行创建 2. 如果满了,则等待池中的进程执行完毕,再创建新的进程 3. 批量创建并且执行进程2. close() 关闭进程池,不再接受新的进程的加入,池中的进程继续执行,不受影响
import multiprocessingimport asynciodef movie(name,n): for i in range(n): print('看电影%s'%name)def music(name,n): for i in range(n): print('听音乐%s'%name)if __name__ == '__main__': # 创建进程 pool = multiprocessing.Pool(2) pool.apply_async(func=movie,args=('背背佳',100)) pool.apply_async(func=music,args=('大风车',100)) pool.close() pool.join()
- Queue
队列:是一种数据结构,先进先出1. Queue对象: 进程间的通信安全队列
import multiprocessingdef zihao(qianbao): i = 1 while True: i+=1 qianbao.put(i)def jinming(qianbao): while True: print(qianbao.get())if __name__ == '__main__': queue = multiprocessing.Queue() zihao_1 = multiprocessing.Process(target=zihao,args=(queue,)) jinming_1 = multiprocessing.Process(target=jinming,args=(queue,)) zihao_1.start() jinming_1.start()