이 글은 Python의 다중 프로세스와 프로세스 풀(Processing library)에 대한 자세한 설명을 중심으로 소개하는데, 실용적 가치가 큰 친구들이 참고하면 됩니다.
환경: win7+python2.7
I 멀티프로세스나 멀티스레딩을 항상 배우고 싶었는데, 몇 가지 기본 지식과 간단한 소개만 보기 전에는 어떻게 적용하는지 이해가 되지 않아서 얼마 전까지 github에서 크롤러 프로젝트를 보았습니다. 바이두 관련 지식 포인트를 살펴보았는데, 이제 기록에 대한 몇 가지 관련 지식 포인트와 응용 프로그램을 적어보겠습니다.
먼저 프로세스가 무엇인지 이야기해 보겠습니다. 컴퓨터에서 프로그램의 활동을 말하며, 프로그램이 실행되면 프로세스가 시작됩니다. 그리고 프로세스는 운영체제의 다양한 기능을 수행하는 데 사용되는 프로세스인 한 시스템 프로세스로 구분됩니다. 실행 중인 상태의 운영 체제 자체와 사용자가 시작한 모든 프로세스는 사용자 프로세스입니다. 프로세스는 운영체제가 자원을 할당하는 단위이다.
직관적으로 말하면 작업 관리자에서 system으로 표시된 사용자 이름은 시스템 프로세스이고, netro는 netro이고 lcacal 서비스는 로컬 서비스입니다. 백과사전에서 찾을 수 있습니다. 그렇지 않으면 되돌릴 수 없습니다.
1. 다중 처리의 간단한 사용
그림에 표시된 것처럼 다중 처리에는 여러 기능이 있습니다. 아직 이해하지 못한 부분이 많습니다. 여기서는 제가 지금까지 알고 있는 것만 이야기하겠습니다.
프로세스 생성:Process(target=주 실행 함수, name=사용자 지정 프로세스 이름은 선택 사항, args= (매개변수))
Method:
is_alive(): 프로세스가 살아 있는지 확인
join([timeout]): 다음 단계를 실행하기 전에 하위 프로세스가 종료됩니다. 프로세스가 차단됩니다. 프로그램이 계속 실행될 수 있도록 시간 초과가 설정됩니다.
run(): 프로세스를 생성하는 경우 개체를 사용할 때 대상을 지정하지 않으면 프로세스의 실행 메서드가 됩니다. 기본적으로 실행
start(): 프로세스 시작, run()
terminate(): 프로세스 종료를 구별하는 것은 그리 간단하지 않은 것 같습니다. psutil 패키지를 사용하는 것이 더 좋을 것 같습니다. .기회가 되면 더 적어보겠습니다.
그중 Process는 start()로 프로세스를 시작합니다.
속성:
authkey: 문서의 authkey() 함수에서 다음 문장을 찾았습니다. 지금까지 관련 응용 프로그램 예제를 찾을 수 없습니다. about? 기사에는
daemon에 대한 언급이 없습니다. 상위 프로세스가 종료된 후 자동으로 종료되며, start() 전에 설정해야 합니다.
exitcode: 프로세스가 실행 중일 때, None입니다. -N이면 신호 N에 의해 종료되었음을 나타냅니다.
name: 프로세스 이름, 사용자 정의
pid: 각 프로세스에는 고유한 PID 번호가 있습니다.
1.Process(),start(),join()
# -*- coding:utf-8 -*- from multiprocessing import Process import time def fun1(t): print 'this is fun1',time.ctime() time.sleep(t) print 'fun1 finish',time.ctime() def fun2(t): print 'this is fun2',time.ctime() time.sleep(t) print 'fun2 finish',time.ctime() if name == 'main': a=time.time() p1=Process(target=fun1,args=(4,)) p2 = Process(target=fun2, args=(6,)) p1.start() p2.start() p1.join() p2.join() b=time.time() print 'finish',b-a
여기서 총 두 개의 프로세스 p1과 p2가 열립니다. arg=(4,)의 4는 fun1 함수의 매개변수입니다. , 여기서 tulpe 유형을 사용하려면 매개변수가 2개 이상인 경우 arg=(매개변수 1, 매개변수 2...)이고, 그런 다음 start()를 사용하여 프로세스를 시작하도록 설정합니다. 그리고 p2 프로세스는 다음 단계를 실행하기 전에 종료됩니다. 아래를 참조하세요. 작업 결과 fun2와 fun1은 기본적으로 작업이 완료되면 동시에 실행되기 시작합니다(fun1은 4초 동안 sleep, fun2는 6초 동안 sleep). print 'finish' 및 b-a 문이 실행됩니다.
this is fun2 Mon Jun 05 13:48:04 2017 this is fun1 Mon Jun 05 13:48:04 2017 fun1 finish Mon Jun 05 13:48:08 2017 fun2 finish Mon Jun 05 13:48:10 2017 finish 6.20300006866 Process finished with exit code 0
start()와 Join()이 다른 위치에 있을 때 무슨 일이 일어나는지 살펴보겠습니다.
# -*- coding:utf-8 -*- from multiprocessing import Process import time def fun1(t): print 'this is fun1',time.ctime() time.sleep(t) print 'fun1 finish',time.ctime() def fun2(t): print 'this is fun2',time.ctime() time.sleep(t) print 'fun2 finish',time.ctime() if name == 'main': a=time.time() p1=Process(target=fun1,args=(4,)) p2 = Process(target=fun2, args=(6,)) p1.start() p1.join() p2.start() p2.join() b=time.time() print 'finish',b-a
결과:
this is fun1 Mon Jun 05 14:19:28 2017 fun1 finish Mon Jun 05 14:19:32 2017 this is fun2 Mon Jun 05 14:19:32 2017 fun2 finish Mon Jun 05 14:19:38 2017 finish 10.1229999065 Process finished with exit code 0
보세요, 이제 fun1 함수가 먼저 실행됩니다. , fun2가 완료된 후 실행되고 print 'finish'가 실행됩니다. 즉, 프로세스 p1이 먼저 실행된 다음 프로세스 p2가 실행됩니다. 이제 Join()의 매력에 도달했습니다. Join()을 주석 처리하고 무슨 일이 일어나는지 다시 확인하세요
# -*- coding:utf-8 -*- from multiprocessing import Process import time def fun1(t): print 'this is fun1',time.ctime() time.sleep(t) print 'fun1 finish',time.ctime() def fun2(t): print 'this is fun2',time.ctime() time.sleep(t) print 'fun2 finish',time.ctime() if name == 'main': a=time.time() p1=Process(target=fun1,args=(4,)) p2 = Process(target=fun2, args=(6,)) p1.start() p2.start() p1.join() #p2.join() b=time.time() print 'finish',b-a
결과:
this is fun1 Mon Jun 05 14:23:57 2017 this is fun2 Mon Jun 05 14:23:58 2017 fun1 finish Mon Jun 05 14:24:01 2017 finish 4.05900001526 fun2 finish Mon Jun 05 14:24:04 2017 Process finished with exit code 0
이번에는 fun1의 실행이 완료되었습니다. 단계), 그런 다음 주 프로세스의 'finish' 인쇄를 계속 실행하고 fun2 실행이 완료된 후 마지막으로 종료됩니다
2.name, daemon, is_alive():
# -*- coding:utf-8 -*- from multiprocessing import Process import time def fun1(t): print 'this is fun1',time.ctime() time.sleep(t) print 'fun1 finish',time.ctime() def fun2(t): print 'this is fun2',time.ctime() time.sleep(t) print 'fun2 finish',time.ctime() if name == 'main': a=time.time() p1=Process(name='fun1进程',target=fun1,args=(4,)) p2 = Process(name='fun2进程',target=fun2, args=(6,)) p1.daemon=True p2.daemon = True p1.start() p2.start() p1.join() print p1,p2 print '进程1:',p1.is_alive(),'进程2:',p2.is_alive() #p2.join() b=time.time() print 'finish',b-a
Result:
this is fun2 Mon Jun 05 14:43:49 2017 this is fun1 Mon Jun 05 14:43:49 2017 fun1 finish Mon Jun 05 14:43:53 2017 <Process(fun1进程, stopped daemon)> <Process(fun2进程, started daemon)> 进程1: False 进程2: True finish 4.06500005722 Process finished with exit code 0
name은 프로세스에 이름을 부여하는 것입니다. print 'process 1:', p1.is_alive(), 'process 2:', p2.is_alive()에 도달하면 p1 프로세스가 종료됩니다(반환). False), p2 프로세스는 여전히 실행 중이지만(True 반환) p2는 Join()을 사용하지 않으므로 daemon=Ture를 사용하므로 상위 프로세스가 종료된 후 자동으로 종료됩니다. p2 프로세스가 종료되기 전에 전체 프로그램이 강제 종료됩니다. .
3.run()
run() 프로세스가 대상 함수를 지정하지 않으면 기본적으로 run() 함수를 사용하여 프로그램을 실행합니다.
# -*- coding:utf-8 -*- from multiprocessing import Process import time def fun1(t): print 'this is fun1',time.ctime() time.sleep(t) print 'fun1 finish',time.ctime() def fun2(t): print 'this is fun2',time.ctime() time.sleep(t) print 'fun2 finish',time.ctime() if name == 'main': a = time.time() p=Process() p.start() p.join() b = time.time() print 'finish', b - a결과:
finish 0.0840001106262결과에서 프로세스 p에는 아무것도 없습니다. 프로세스가 정상적으로 실행되도록 하기 위해 우리 Jiangzi는 다음과 같이 썼습니다.
# -*- coding:utf-8 -*- from multiprocessing import Process import time def fun1(): print 'this is fun1',time.ctime() time.sleep(2) print 'fun1 finish',time.ctime() def fun2(t): print 'this is fun2',time.ctime() time.sleep(t) print 'fun2 finish',time.ctime() if name == 'main': a = time.time() p=Process() p.run=fun1 p.start() p.join() b = time.time() print 'finish', b - a결과:
this is fun1 Mon Jun 05 16:34:41 2017 fun1 finish Mon Jun 05 16:34:43 2017 finish 2.11500000954 Process finished with exit code 0목적 함수에는 매개변수가 있습니다.
# -*- coding:utf-8 -*- from multiprocessing import Process import time def fun1(t): print 'this is fun1',time.ctime() time.sleep(t) print 'fun1 finish',time.ctime() def fun2(t): print 'this is fun2',time.ctime() time.sleep(t) print 'fun2 finish',time.ctime() if name == 'main': a = time.time() p=Process() p.run=fun1(2) p.start() p.join() b = time.time() print 'finish', b - a결과:
this is fun1 Mon Jun 05 16:36:27 2017 fun1 finish Mon Jun 05 16:36:29 2017 Process Process-1: Traceback (most recent call last): File "E:\Anaconda2\lib\multiprocessing\process.py", line 258, in _bootstrap self.run() TypeError: 'NoneType' object is not callable finish 2.0529999733 Process finished with exit code 0목적함수에 매개변수가 있는데 왜 예외가 발생했는지 아직 이유를 알 수 없지만, 실제로 실행할 프로세스에 마지막 매개변수가 주어지면 다른 매개변수가 없으면 이 예외가 발생합니다. 아는 사람이 있으면 알려주세요.
2. 프로세스 풀
对于需要使用几个甚至十几个进程时,我们使用Process还是比较方便的,但是如果要成百上千个进程,用Process显然太笨了,multiprocessing提供了Pool类,即现在要讲的进程池,能够将众多进程放在一起,设置一个运行进程上限,每次只运行设置的进程数,等有进程结束,再添加新的进程
Pool(processes =num):设置运行进程数,当一个进程运行完,会添加新的进程进去
apply_async(函数,(参数)):非阻塞,其中参数是tulpe类型,
apply(函数,(参数)):阻塞
close():关闭pool,不能再添加新的任务
terminate():结束运行的进程,不再处理未完成的任务
join():和Process介绍的作用一样, 但要在close或terminate之后使用。
1.单个进程池
# -*- coding:utf-8 -*- from multiprocessing import Pool import time def fun1(t): print 'this is fun1',time.ctime() time.sleep(t) print 'fun1 finish',time.ctime() def fun2(t): print 'this is fun2',time.ctime() time.sleep(t) print 'fun2 finish',time.ctime() if name == 'main': a=time.time() pool = Pool(processes =3) # 可以同时跑3个进程 for i in range(3,8): pool.apply_async(fun1,(i,)) pool.close() pool.join() b=time.time() print 'finish',b-a
结果:
this is fun1 Mon Jun 05 15:15:38 2017 this is fun1 Mon Jun 05 15:15:38 2017 this is fun1 Mon Jun 05 15:15:38 2017 fun1 finish Mon Jun 05 15:15:41 2017 this is fun1 Mon Jun 05 15:15:41 2017 fun1 finish Mon Jun 05 15:15:42 2017 this is fun1 Mon Jun 05 15:15:42 2017 fun1 finish Mon Jun 05 15:15:43 2017 fun1 finish Mon Jun 05 15:15:47 2017 fun1 finish Mon Jun 05 15:15:49 2017 finish 11.1370000839 Process finished with exit code 0
从上面的结果可以看到,设置了3个运行进程上限,15:15:38这个时间同时开始三个进程,当第一个进程结束时(参数为3秒那个进程),会添加新的进程,如此循环,直至进程池运行完再执行主进程语句b=time.time() print 'finish',b-a .这里用到非阻塞apply_async(),再来对比下阻塞apply()
# -*- coding:utf-8 -*- from multiprocessing import Pool import time def fun1(t): print 'this is fun1',time.ctime() time.sleep(t) print 'fun1 finish',time.ctime() def fun2(t): print 'this is fun2',time.ctime() time.sleep(t) print 'fun2 finish',time.ctime() if name == 'main': a=time.time() pool = Pool(processes =3) # 可以同时跑3个进程 for i in range(3,8): pool.apply(fun1,(i,)) pool.close() pool.join() b=time.time() print 'finish',b-a
结果:
this is fun1 Mon Jun 05 15:59:26 2017 fun1 finish Mon Jun 05 15:59:29 2017 this is fun1 Mon Jun 05 15:59:29 2017 fun1 finish Mon Jun 05 15:59:33 2017 this is fun1 Mon Jun 05 15:59:33 2017 fun1 finish Mon Jun 05 15:59:38 2017 this is fun1 Mon Jun 05 15:59:38 2017 fun1 finish Mon Jun 05 15:59:44 2017 this is fun1 Mon Jun 05 15:59:44 2017 fun1 finish Mon Jun 05 15:59:51 2017 finish 25.1610000134 Process finished with exit code 0
可以看到,阻塞是当一个进程结束后,再进行下一个进程,一般我们都用非阻塞apply_async()
2.多个进程池
上面是使用单个进程池的,对于多个进程池,我们可以用for循环,直接看代码
# -*- coding:utf-8 -*- from multiprocessing import Pool import time def fun1(t): print 'this is fun1',time.ctime() time.sleep(t) print 'fun1 finish',time.ctime() def fun2(t): print 'this is fun2',time.ctime() time.sleep(t) print 'fun2 finish',time.ctime() if name == 'main': a=time.time() pool = Pool(processes =3) # 可以同时跑3个进程 for fun in [fun1,fun2]: for i in range(3,8): pool.apply_async(fun,(i,)) pool.close() pool.join() b=time.time() print 'finish',b-a
结果:
this is fun1 Mon Jun 05 16:04:38 2017 this is fun1 Mon Jun 05 16:04:38 2017 this is fun1 Mon Jun 05 16:04:38 2017 fun1 finish Mon Jun 05 16:04:41 2017 this is fun1 Mon Jun 05 16:04:41 2017 fun1 finish Mon Jun 05 16:04:42 2017 this is fun1 Mon Jun 05 16:04:42 2017 fun1 finish Mon Jun 05 16:04:43 2017 this is fun2 Mon Jun 05 16:04:43 2017 fun2 finish Mon Jun 05 16:04:46 2017 this is fun2 Mon Jun 05 16:04:46 2017 fun1 finish Mon Jun 05 16:04:47 2017 this is fun2 Mon Jun 05 16:04:47 2017 fun1 finish Mon Jun 05 16:04:49 2017 this is fun2 Mon Jun 05 16:04:49 2017 fun2 finish Mon Jun 05 16:04:50 2017 this is fun2 Mon Jun 05 16:04:50 2017 fun2 finish Mon Jun 05 16:04:52 2017 fun2 finish Mon Jun 05 16:04:55 2017 fun2 finish Mon Jun 05 16:04:57 2017 finish 19.1670000553 Process finished with exit code 0
看到了,在fun1运行完接着运行fun2.
另外对于没有参数的情况,就直接 pool.apply_async(funtion),无需写上参数.
在学习编写程序过程,曾遇到不用if _name_ == '_main_':而直接运行程序,这样结果会出错,经查询,在Windows上要想使用进程模块,就必须把有关进程的代码写在当前.py文件的if _name_ == ‘_main_' :语句的下面,才能正常使用Windows下的进程模块。Unix/Linux下则不需要。原因有人这么说:在执行的時候,由于你写的 py 会被当成module 读进执行。所以,一定要判断自身是否为 _main_。也就是要:
if name == ‘main' : # do something.
这里我自己还搞不清楚,期待以后能够理解
위 내용은 Python의 다중 프로세스 및 프로세스 풀(처리 라이브러리)에 대한 예제 코드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!