线程是最小的执行单元,而进程至少由一个线程组成。
1.单个子进程
multiprocessing模块提供了一个Process类来代表一个进程对象。
代码:
def run_child(name): for i in range(4): print('我是子进程 {} : {}'.format(name,os.getpid())) if __name__=='__main__': print('父进程是 {}'.format(os.getpid())) p=Process(target=run_child,args=('banana',))#创建一个Process实例 print('子进程接下来就要执行了...') p.start() #启动子进程 p.join() #等待子进程结束后继续往下运行 print('所有进程都执行完了.')
输出:
2.多个子进程
用进程池的方式创建多个子进程。
(1)apply:
是阻塞的,等待当前子进程执行完毕后,才执行下一个进程。
流程:主进程先开始运行,碰到子进程后,操作系统立刻切换到子进程,等待所有子进程运行完毕。然后再切换到主进程,运行剩余的部分。
(2)apply_async:
是异步非阻塞的,不用等待当前子进程执行完毕,根据系统调度来进行进程切换。
流程:主进程先开始运行,碰到子进程后,主进程会"视而不见",先执行完自己的再说。直到操作系统切换进程的时候,再交给子进程运行。(由于代码少,往往主进程会执行完毕。)
p.join():
用来阻塞主进程,如果不阻塞主进程,会导致主进程往下运行到结束。
调用join()之前必须先调用close(),否则会报错。
代码:from multiprocessing import Pool import os,time #在进程池执行的函数 def run_child(name): print('我是子进程 {} {}'.format(name,os.getpid())) start=time.time() time.sleep(1) end=time.time() print('子进程 {0} 运行了 {1:.2f} 秒.'.format(name,(end-start))) if __name__=='__main__': print('父进程是 {}'.format(os.getpid())) p=Pool(4) #进程池最大运行数 for i in range(6): #p.apply(run_child,args=(i,)) #阻塞 p.apply_async(run_child,args=(i,)) #非阻塞 print('先等等吧...') p.close() #关闭进程池,使其不在接受新的任务 p.join() #用来阻塞主进程 print('所有进程都执行完了.')
非阻塞输出:
阻塞输出:
3.运行外部命令
subprocess.call(command)方法
可以用于执行一个外部命令,该方法不能返回执行的结果,只能返回执行的状态码:成功(0)或错误(非0)。
command可以是列表,也可以是字符串,作字符串时需要用原生的shell来执行。
代码:
import subprocess print('启动notepad...') n=subprocess.call(['notepad']) print('code:',n) #subprocess.check_call()处理异常 try: subprocess.check_call("notepad1",shell=True) except subprocess.CalledProcessError as e: print("异常是:",e)
输出:
4.进程的通信
mutiprocessing模块提供的Queue和Pipe可以实现进程间的通信。
(1)Queue
代码:
from multiprocessing import Process,Queue import os def shop(q): print('我要购买水果的进程 {}.'.format(os.getpid())) fruit_list=['banana','apple','orange'] q.put(fruit_list) def look(q): print('我要看看购物车的进程 {}.'.format(os.getpid())) value=q.get() print('原来我挑选了 {}'.format(value)) if __name__ == '__main__': #父进程创建Queue,并传给各子进程 q=Queue() #两个子进程 p1=Process(target=shop,args=(q,)) p2=Process(target=look,args=(q,)) p1.start() p2.start() p1.join() print('p1结束了!') p2.join() print('p2结束了!')
输出:
(2)Pipe管道
可以是单向或双向(默认)。
代码:
from multiprocessing import Process,Pipe import os def client(p): str='hello,小明...' p.send(str) print('to service:',str) def service(p): print('from client:',p.recv()) if __name__=='__main__': print('父进程是 {}'.format(os.getpid())) p=Pipe() p1=Process(target=client,args=(p[0],)) p2=Process(target=service,args=(p[1],)) p1.start() p2.start() p1.join() p2.join() print('所有进程都结束了!')
输出: