38 day of python
IPC进程之间的通信
管道 pipe
IPC通信的一种机制,队列就是基于管道来完成通信的,但是管道是原生的通信方式
在进程之间会产生数据不安全的情况,需要自己手动加锁来处理
管道在数据传输过程中,还涉及到一个端口管理,这个需要我们在代码中做处理才能使代码更完善。
队列
管道 + 锁
进程之间数据安全
数据共享
进程池
什么时候用进程池
面向高计算型的场景 采用多进程
如果开启的进程数超过
有几个CPU就能够同时运行几个进程
今日内容:
进程
进程池
线程
理论
Threading.Thread来创建线程
同步请求的
import time from multiprocessing import Pool def wahaha(): time.sleep(1) return True if __name__ == '__main__': p = Pool(5) # CPU的个数 或者+1 ret_l = [] for i in range(20): ret = p.apply(func = wahaha) # 同步的,不用 print(ret)
异步提交,不获取返回值
def wahaha(): time.sleep(1) print(os.getpid()) if __name__ == '__main__': p = Pool(5) # CPU的个数 或者 +1 ret_l = [] for i in range(20): ret = p.apply_async(func = wahaha) # async 异步的 ret_l.append(ret) p.close() # 关闭 不是进程池中的进程不工作了 # 而是关闭了进程池,让任务不能再继续提交了 p.join() # 等待这个池中提交的任务都执行完 # # 表示等待所有子进程中的代码都执行完 主进程才结束
异步提交,获取返回值,等待所有任务都执行完毕之后再统一获取结果
def wahaha(): time.sleep(1) print(os.getpid()) return True if __name__ == '__main__': p = Pool(5) # CPU的个数 或者 +1 ret_l = [] for i in range(20): ret = p.apply_async(func = wahaha) # async 异步的 ret_l.append(ret) p.close() # 关闭 进程池中的进程不工作了 # 而是关闭了进程池,让任务不能再继续提交了 p.join() # 等待这个池中提交的任务都执行完 for ret in ret_l: print(ret.get())
异步提交,获取返回值,一个任务执行完毕之后就可以获取到一个结果(顺序是按照提交任务的顺序)
def wahaha(): time.sleep(1) print(os.getpid()) return True if __name__ == '__main__': p = Pool(5) # CPU的个数 或者 +1 ret_l = [] for i in range(20): ret = p.apply_async(func = wahaha) # async 异步的 ret_l.append(ret) for ret in ret_l: print(ret.get())
异步的 apply_async
1.如果是异步的提交任务,那么任务提交之后进程池和主进程也异步了,
主进程不会自动等待进程池中的任务执行完毕
2.如果需要主进程等待,需要p.join
但是join的行为是依赖close
3.如果这个函数是有返回值的
也可以通过ret.get()来获取返回值
但是如果一边提交一遍获取返回值会让程序变成同步的
所以要想保留异步的效果,应该讲返回对象保存在列表里,所有任务提交完成之后再来取结果
这种方式也可以去掉join,来完成主进程的阻塞等待池中的任务执行完毕
import socket from multiprocessing import Pool def talk(conn): try: while True: conn.send(b'123') print(conn.recv(1024)) finally: conn.close() if __name__ == '__main__': p = Pool(5) sk = socket.socket() sk.bind(('127.0.0.1',9999)) sk.listen() while True: conn,addr = sk.accept() p.apply_async(func=talk,args=(conn,))
import socket import os sk = socket.socket() sk.connect(('127.0.0.1',9999)) while True: print(sk.recv(1024)) sk.send(str(os.getpid()).encode('utf-8'))
异步提交,获取返回值,从头到尾一个任务执行完毕之后就可以获取到一个结果
def wahaha(num): time.sleep(random.random()) print('pid : ',os.getpid(),num) return num def back(arg): print('call_back : ',os.getpid(),arg) if __name__ == '__main__': print('主进程',os.getpid()) p = Pool(5) # CPU的个数 或者 +1 for i in range(20): ret = p.apply_async(func = wahaha,args=(i,),callback=back) # async 异步的 p.close() p.join()
回调函数 _ 在主进程中执行
在发起任务的时候 指定callback参数
在每个进程执行完apply_async任务之后,返回值会直接作为参数传递给callback的函数,执行callback函数中的代码
北京 30min 30min +5min 5min + 5min
建设 20min 直接办 + 5min 5min
中国 1h 20min +5 25min + 5min
农业 2h 55min + 5min 55min + 5min
工商 15min 5min 15min + 5min
2h10min
2h05min
进程总结
进程三状态
同步异步阻塞非阻塞
请解释异步非阻塞
给开发完成的所有装饰器+log
是计算机中最小的资源分配单位
进程的创建 Process
进程之间的异步 本身子进程主进程之间都是异步的
进程之间的同步控制 Lock Semaphore Event
进程之间的数据隔离 本身进程与进程之间都是数据隔离的
进程之间通信 IPC 管道 队列
数据共享 Manager
进程池 -可以获取返回值
同步调用 - 基本不用的
异步调用 - 重要的
apply_async
get获取结果
close
join
回调函数 Pool 回调函数在主进程中执行
apply_async(func = wahaha,callback = back)
线程概念
进程
是计算机中最小的资源分配单位
在利用多个CPU执行的过程中,对多个程序的资源进行管理和隔离
进程的弊端
开启和关闭 以及 切换 都会带来很大的时间开销
过多的进程还会造成操作系统调度的压力
线程
线程是CPU调度的最小单位
每个进程中至少有一个线程
实际上执行代码的是线程
线程属于进程
进程负责获取操作系统分配给我的资源
线程负责执行代码
从代码的角度上来看
多进程
开启和结束 时间开销大
切换的效率低
内存隔离
多线程
开启和结束 时间开销非常小
切换效率高
内存不隔离
Cpython解释器下的全局解释器锁
在同一个进程中的多个线程在同一时刻只能有一个线程访问CPU
多线程无法形成并行
锁的线程
什么时候才会有到CPU
程序计算的时候
IO阻塞
是不会用到CPU的
Jpython解释器就没有全局解释器锁
pypy解释没有全局解释器锁
4cpu
起四个进程
进程里起线程
threading模块
import os import time from threading import Thread def func(): time.sleep(1) print(123,os.getpid()) print(123,os.getpid()) for i in range(10): func() 同步 Thread(target=func).start() 异步

浙公网安备 33010602011771号