进程相关总结
队列 队列 : 先进先出、数据进程安全 队列实现方式: 管道 + 锁 生产者消费者模型 : 解决数据供需不平衡 管道 双向通信 数据进程不安全 EOFError: 管道是由操作系统进行引用计数的, 必须在所有进程中关闭管道后才能生成EOFError异常 数据共享(不常用) Manager list dict 数据进程不安全的 进程池 存放进程的容器 在进程创建之初,创建固定个数的进程 会被多个任务循环利用 节省了进程创建和销毁的时间开销 降低了操作系统调度进程的压力 信号量和进程池的区别 信号量 n个任务开启n个进程, 但同一时间只能有固定个数的进程在执行 进程在等待被执行 进程池 n个任务开启固定个数的进程 因此同一时间只能有固定个数的进程在执行 任务在等待被执行
队列是内置锁的,所以别的应用调用它,是安全的。
凡是涉及到手动加锁的,都是不安全的。常用的一般都是消息中间件
没有返回值的情况
close和join成对使用
import time from multiprocessing import Pool def wahaha(i): time.sleep(1) print('*'*i) if __name__ == '__main__': p = Pool(5) #建议的数量是CPU核数+1 for i in range(5): p.apply_async(func=wahaha,args=(i,)) p.close() # 不能再提交新的任务 p.join() # 等待池中的任务都执行完
执行输出:
*
**
***
****
有返回值的情况
import time from multiprocessing import Pool def wahaha(i): time.sleep(1) return '*'*i if __name__ == '__main__': p = Pool(5) #建议的数量是CPU核数+1 res_1 = [] for i in range(5): res = p.apply_async(func=wahaha,args=(i,)) res_1.append(res) for i in res_1:print(i.get())
执行输出:
*
**
***
****
总结:
主进程默认等待子进程结束 —— 守护进程
普通的进程 : 根据你调用的函数执行结束它就结束了
进程池里的进程
没有返回值:
在提交任务之后:
p.close() 不能再提交新的任务
p.join() 等待池中的任务都执行完
有返回值的时候:
在提交任务之后:
for i in res_l:print(i.get())
第二种写法:使用map
它不能获取返回值,参数必须是一个可迭代对象
import time from multiprocessing import Pool def wahaha(i): time.sleep(1) print('*'*i) if __name__ == '__main__': p = Pool(5) #建议的数量是CPU核数+1 p.map(func=wahaha,iterable=range(5)) # iterable接收一个可迭代对象
执行输出:
**
*
***
****
如果不需要返回值得,使用map即可
回调函数
回调函数在什么时候执行
子进程的任务执行完毕之后立即触发
回调函数的参数
子进程的返回值
回调函数是由谁执行的
主进程执行的
在哪儿用?
爬虫 :
如果要爬取多个格式相同的网页
真正影响程序效率的是网络的延迟
计算 分析 处理网页的时间是很快的
如果主进程要处理很久,那么就不适合用回调函数
当你不确定,到底有没有回调函数快?测试一下就知道了。
先不用回调函数,打印执行时间
再用回调函数,打印执行时间,对比一下,就知道了。