day10-进程池的使用
一、概述
本篇博客主要写进程锁,__name__ == "__main__"函数作用,以及进程池的使用。
二、进程同步
2.1、进程锁
说明:通过multiprocessing 中的Lock模块来实现进程锁。
1 from multiprocessing import Lock,Process 2 import os 3 4 def f(l,i): 5 l.acquire() 6 try: 7 print("hello world",i) 8 finally: 9 l.release() 10 11 12 if __name__ == '__main__': 13 lock=Lock() 14 for i in range(10): 15 p=Process(target=f,args=(lock,i,)) 16 p.start() 17 p.join()
1、这边不禁的有个疑问,就是进程中不是相互独立的吗?为啥还要加锁呐?
虽然每个进程都是独立运行的,但是问题来了,它们共享一块屏幕。这个锁存在的意义就是屏幕共享。如果也想抱着打印数据,而我想也想打印数据的情况,就有可能乱套了,然后通过这个锁来控制,去打印的时候,这个屏幕只有我独占,导致屏幕不会乱。
2、代码中的__name__ == "__main__"是干嘛用的?
它的作用是为了区分你是主动执行这个脚本还是从别的地方把它当做一个模块去调用。如果主动执行这个脚本,那么__name__ == "__main__" 以下的代码就会执行,如果其他模块导入的,则在其他模块中不执行__name__ == "__main__"以下的代码。这边一般在一个模块中测试用的,但是其他模块又不能执行这部分代码。
三、进程池
进程池的作用:防止启动太多的进程把系统干趴下,才有了进程池的限制,比如说,你起了100个进程,会变慢,起一个进程相当于克隆一个父进程,父进程占1G内存空间,100个进程就占101G的内存,所以进程池就是在同一时间允许多个进程在cpu上运行。
3.1、apply
说明:说明:这个说明是同步执行的,也就是串行执行的
1 from multiprocessing import Pool 2 import time,os 3 4 def foo(i): 5 time.sleep(2) 6 print("in process:",os.getpid()) 7 return i+100 8 9 if __name__ == '__main__': 10 pool=Pool(processes=5) 11 #pool=pool(5) 12 for i in range(10): 13 pool.apply(func=foo,args=(i,)) 14 print("end") 15 pool.close() 16 pool.join()
注:这边的5个进程只是挂起了,并没有真正的去执行,但是执行的时候,只能执行这个5个进程。这个apply是同步的,也就是串行的,一般不用。
3.2、apply_async
说明:异步执行,也就是并行执行。
1 from multiprocessing import Pool 2 import time,os 3 4 def foo(i): 5 time.sleep(1) 6 print("in the process:",os.getpid()) 7 return i+100 8 9 if __name__ == '__main__': 10 11 pool=Pool(5) 12 13 for i in range(10): 14 pool.apply_async(func=foo,args=(i,)) 15 16 print("end") 17 pool.close() 18 pool.join()
注:最后的pool.join()不能省略,不然的话,这个pool的进程池就直接关闭了, 它不会等待执行的结果的。
3.3、异步下的回调函数
说明:在计算机中,这个程序执行完毕之后,再回调过来执行这个Bar。
1 from multiprocessing import Process,Pool 2 import time,os 3 4 def Foo(i): 5 time.sleep(2) 6 print("in process",os.getpid()) 7 return i+100 8 9 def Bar(arg): 10 print("...>exec done",arg,os.getpid()) #打印进程号,查看是谁调用 11 #子进程调用,还是父进程调用 12 13 if __name__ == '__main__': 14 pool=Pool(processes=2) 15 print("主进程",os.getpid()) #主进程的进程号 16 17 for i in range(3): 18 pool.apply_async(func=Foo,args=(i,),callback=Bar) 19 print("end") 20 pool.close() 21 pool.join()
#输出结果
主进程 296
end
in process 7208
...>exec done 100 296
in process 8476
...>exec done 101 296
in process 7208
...>exec done 102 296
说明:
- 回调函数说明fun=Foo干不完就不执行bar函数,等Foo执行完就去执行Bar
- 这个回调函数是主进程去调用的,而不是每个子进程去调用的。
回调函数的用处:
比如说你从各个机器上备份完毕,在回调函数中自动写一个脚本,说备份完毕。
回调函数是主进程调用的原因?
如果是子进程去调用这个回调函数,有多少个子进程就有多少个连接,如果是主进程的话,只需要一次长连接就可以了,这个效率就高了。

浙公网安备 33010602011771号