python从入门到放弃之进程进阶篇
什么我们得了解清楚什么是进程,进程就是系统分配的一个资源单位,真正在程序中干活得是线程,默认是每个进程中都拥有一个线程
然后我们在了解下什么是进程池这个概念
进程池是的数量是取决于我当前电脑的逻辑处理器此时我们程序是异步并发的程序(即多个CPU同时执行多个任务)而我们之前学的进程下面创建子进程是异步并行的程序(即一个CPU执行多个任务)这既是两者之间的差别
Process 和 Pool 区别:
Process : 属于异步并发程序,主进程会默认等待子进程全部执行完毕之后,在终止程序
Pool : 属于异步并行程序,在没有任何阻塞的情况下,只要主进程执行完毕,会立刻终止所有子进程;
p = Pool(6):
代表同一时间最多允许并行6个进程;
进程池pool里面的参数
如果Pool不加任何参数,默认使用的是os.cpu_count()获取到的数量 逻辑处理器
如果加了参数,就使用当前参数值,所代表的是同一时间最大允许的进程数(并行)
在进程池中,如果一个进程执行任务的速度太快,会包揽更多的任务执行,就不会创建新的进程;
# (1) 比较进程池和进程之间的速度 => 进程池速度更快
1 def func(num):
2 print(os.getpid())
3 # print(num)
4 # time.sleep(0.1)
5 for i in range(1000000):
6 pass
7 # 27612 27524 25940 26448 27520 26204
8 if __name__ == "__main__":
9 # 记录开始时间
10 startime = time.time()
11 # 1.创建进程池
12 p = Pool(6)
13 for i in range(100):
14 # 2.异步并行执行进程
15 p.apply_async(func,args=(i,))
16 # 3.关闭进程池
17 p.close()
18 # 4.等待子进程全部执行结束之后,在向下执行
19 p.join()
20 # 记录结束时间
21 endtime = time.time()
22 print("1号运行的时间是:",endtime-startime) # 0.5326602458953857
23 print("进程池运行结束 ... ")
24
25 # 计算process运行的时间
26 startime = time.time()
27 lst = []
28 for i in range(100):
29 p = Process(target=func,args=(i,))
30 p.start()
31 lst.append(p)
32
33 for i in lst:
34 i.join()
35 endtime = time.time()
36 print("2号运行的时间是:",endtime-startime) # 2.051966428756714
37 print("process运行结束 ..")
# 旧版进程池,主进程执行结束后,立刻终止子进程;
def func(num): print(os.getpid()) if __name__ == "__main__": # 1.创建进程池 p = Pool(6) for i in range(100): # 2.异步并行执行进程 p.apply_async(func,args=(i,)) # 3.关闭进程池 p.close() # 4.等待子进程全部执行结束之后,在向下执行 p.join() print("进程池运行结束 ... ")
# (2) apply 同步程序,可以直接获取子进程中的返回值(了解)
def task(num): print("num:%s 进程号%s"%(num,os.getpid())) return os.getpid() if __name__ == "__main__": # 同一时间最多运行并行4个进程 p = Pool(4) for i in range(20): res = p.apply(task,args=(i,)) print(">>>",res) print(" 主程序执行结束 ... ")
# (3) apply_async 异步程序 , 可以直接通过get获取子进程中的返回值
1 def task(num): 2 time.sleep(random.uniform(0.1,1)) 3 # print("num:%s 进程号%s"%(num,os.getpid())) 4 return os.getpid() 5 6 if __name__ == "__main__": 7 lst = [] 8 setvar = set() 9 p = Pool() 10 for i in range(20): 11 res = p.apply_async(task,args=(i,)) 12 lst.append(res) 13 14 # print(lst) 15 for i in lst: 16 # 用来获取当前子进程的返回值 get函数本身含有阻塞,不加close和join一样可以 17 res = i.get() 18 # print(res) 19 setvar.add(res) 20 21 print(setvar) # {28136, 25480, 20472, 28012, 27344, 24984} 22 23 # 3.关闭进程池 24 # p.close() 25 # 4.等待子进程全部执行结束之后,在向下执行 26 # p.join() 27 28 print("finish")
# (4) map (与高阶函数map使用方法一样,区别在于并发和并行) 返回列表
def task(num): print("num:%s 进程号%s"%(num,os.getpid())) time.sleep(0.1) return num ** 2 if __name__ == "__main__": p = Pool() res = p.map(task,range(100)) print(res) print("主进程 finish")
# (5) close 和 join 同时使用,或者同时不适用,必须是一对
def task(num):
# print("num:%s 进程号%s"%(num,os.getpid()))
# time.sleep(0.1)
return num ** 2
if __name__ == "__main__":
lst = []
p = Pool()
for i in range(20):
# res 返回的是异步的进程对象
res = p.apply_async(task,args=(i,))
lst.append(res)
"""
for i in lst:
# 在获取返回值的同时,加了阻塞
print(i.get())
"""
# 关闭进程池
p.close()
# p.apply_async(task,args=(100))
p.join()
print("主进程 finish")