1.在Python中,能够经过os.fork()建立子进程,可是这种方式智能在'linux'和'unix'以及'mac'下面使用,不能跨平台,因此通常不推荐使用这种方式。
2.使用'multiprocessing'模块也能够建立多进程,而且这种方式在写起来更加简单,而且支持跨平台,
因此通常推荐使用'multiprocessing'的方式来写多进程的代码。python
'multiprocessing'这个模块下面有一个'Process'的类,使用这个类能够建立一个多进程,使用方式以下:linux
from multiprocessing import Process import os def demo(): print('我是子进程--->') print('子进程进程号是%s'%(os.getpid())) print('父进程进程号是%s'%(os.getppid())) if __name__ == '__main__': p = Process(target=demo) p.start() print('主进程的进程号是%s'%(os.getpid()))
须要注意一点的是,若是在'windows'操做系统下,
全部和进程建立相关的代码都必须放在'if name == 'main''下面,不然会报错。windows
1.经过'os.getpid()'能够获取到当前这个进程的id
2.经过'os.getppid()'能够获取到当前这个进程的父进程的idapp
若是在父进程中执行完全部代码后,还有子进程在执行,那么父进程会等待子进程执行完全部代码后再退出。async
'join'方法可让你的主进程阻塞,直到这个子进程执行完毕之后才会执行主进程后面的代码。函数
from multiprocessing import Process import os import time def demo(): for i in range(5): print('子进程') time.sleep(1) if __name__ == '__main__': p = Process(target=demo) p.start() print('主进程') p.join() # join方法的时候,就至关于主进程会阻塞在这个地方,直到这个子进程执行完毕之后才会执行父进程后的代码 print('执行完毕')
1.使用'Process'做为父类,从新自定义一个类。
2.在自定义的类中,重写父类的'run'方法,这个是必须的,其余方法,就按照你平时如何写就能够了。
3.使用自定义的进程类建立子进程的时候,不须要传'target'参数。操作系统
from multiprocessing import Process import os class MyProcess(Process): def run(self): print('子进程的id:%s' % os.getpid()) print('父进程的id:%s' % os.getppid()) for i in range(5): print('子进程:%s'%i) if __name__ == '__main__': p = MyProcess() p.start() print('父进程的id:%s'%os.getpid()) print('子进程开始了') p.join() print('子进程结束了')
1.'multiprocessing'中的'Pool'能够实现一个容器,来管理子进程。
2.使用进程池有什么好处,进程池能够控制同一时刻,最多只能有多少个进程在运行。
3.主进程不会等待进程池中的子进程都执行完毕之后再退出,二十若是父进程代码执行完毕之后,就会将整个程序都退出,
全部咱们在写进程池的时候,应该使用'pool.join()'来保证进程池中全部的子进程都可以执行完成。
4.'apply_async'至关因而并联的方式执行(同一时刻只能执行一个任务,而且只能等待前面的任务执行完后,才能执行后面的任务)unix
from multiprocessing import Pool import os import time def demo(num): for x in range(5): print('子进程id:%s ,值:%s'% (os.getpid(),num)) time.sleep(2) if __name__ == '__main__': # 这个池子中同一时刻最多只能有3个进程 pool = Pool(2) for x in range(10): pool.apply_async(demo,args=(x,)) # 关闭进程池,不能再添加新进程了 pool.close() # 主进程把子进程添加到进程池中后,不会等待进程池中其余的子进程都执行完毕后再退出, # 而是当主进程的代码执行完毕后悔马上退出,所以若是这个地方没有join,那么子进程将得不到执行。 pool.join()
在程序中建立了子进程,子进程会彻底copy一份主进程的环境,包括变量、函数、类等。
因此在子进程中使用变量、函数等的时候,实际上是使用的是子进程中的那一份,跟主进程没有任何关系。code
from multiprocessing import Process AGE = 1 def hello(): print('hello') def greet(names): global AGE AGE += 1 names.append('ketang') print('=====子进程代码=====') print('AGE的值:%d, AGE的id:%s' % (AGE,id(AGE))) print('names:%s' % names) print(id(hello)) print('=====子进程代码=====') if __name__ == '__main__': names = ['demo'] p = Process(target=greet,args=(names,)) p.start() p.join() print('=====父进程代码=====') print('AGE的值:%d, AGE的id:%s' % (AGE,id(AGE))) print('names:%s' % names) print(id(hello)) print('=====父进程代码=====')
Queue
消息队列:from multiprocessing import Queue # Queue能够指定maxsize的值 # 之后这个队列中就只能装maxsize个值 # 若是不指定,那么就是为-1 # -1 意味着能够装任意多个消息,直到你的内存满了 q = Queue(3) # put方法,能够传递任意数据类型的消息 q.put('m1') q.put('m2') q.put('m3') # qsize: 获取这个消息队列中总共的消息数量 print('qsize:%s' % q.qsize()) # full, 若是消息队列满了,那么会返回True,不然返回False print(q.full()) # empty:若是消息队列为空,那么会返回True,不然返回False print(q.empty()) # put方法默认是阻塞的方式 # 若是消息队列已经满了,那么会阻塞在这个地方,直到这个消息队列没有满为止 # block参数:能够设置为False,若是为False,那么意味着不会阻塞,若是消息队列满了,那么会立马抛出一个异常 # timeout参数:指定阻塞的最长时间。若是超过了这个时间就再也不阻塞,而是抛出一个异常。 # q.put('m4',block=True,timeout=2) # put_nowait:其实等价于q.put(obj,block=False) # q.put_nowait('m4') # print('finished') # get方法:获取到的是第一个添加进去的值。 # get方法:除了获取这个值外,还会把这个值从消息队列中删除掉 # block参数:默认是等于True,即以阻塞的方式获取值,若是这个队列中没有任何消息,那么会阻塞到这个地方。若是block=False,那么若是队列中没有值,就会当即抛出异常。 # timeout参数:指定阻塞的最长时间,若是超过了这个时间就再也不阻塞,而是抛出一个异常 print(q.get()) print(q.get()) print(q.get()) print(q.get(block=True,timeout=2))
Queue
作进程间通讯:Process
进程作通讯:直接使用Queue
的对象座位进程的参数就能够了。Pool
进程作通讯,应该使用multiprocessing.Manager().Queue()
对象来作通讯,multiprocessing.Queue()
是同样的。from multiprocessing import Process,Queue import os def write(q): for x in ['m1','m2','m3']: q.put(x) print('子进程%s已经存放了消息:%s' % (os.getpid(),x)) def read(q): while True: try: msg = q.get(block=False) print('子进程%s已经读取了消息:%s' % (os.getpid(),msg)) except: print('全部消息都已经取出来了') break if __name__ == '__main__': q = Queue() pw = Process(target=write,args=(q,)) pr = Process(target=read,args=(q,)) pw.start() pr.start() pw.join()
from multiprocessing import Process,Queue,Pool,Manager import os def write(q): for x in ['m1','m2','m3']: q.put(x) print('子进程%s已经存放了消息:%s' % (os.getpid(),x)) def read(q): while True: try: msg = q.get(block=False) print('子进程%s已经读取了消息:%s' % (os.getpid(),msg)) except: print('全部消息都已经取出来了') break if __name__ == '__main__': q = Manager().Queue() pool = Pool(2) pool.apply(func=write,args=(q,)) pool.apply(func=read,args=(q,))