一、进程、程序
1.编写完成的代码,在没有运行的时候,称之为程序
2.正在运行着代码,称之为进程
二、用fork创建进程

import os res = os.fork() if res == 0: while True: print('111111') time.sleep(1) else: while True: print('22222') time.sleep(1) #结果为: 111111 22222 111111 22222
1.os.getpid():获取当前进程id
2.os.getppid():获取父进程的id
三、一些知识点
1.全局变量在多个进程间不共享
四、process创建子进程

from multiprocessing import Process def test(): pass p = Process(target=test) p.start() #让这个进程开始执行test里面的代码
1.用process创建的子进程,在子进程结束之后主进程才会结束
2.p.join([timeout]) 堵塞,在子进程执行完毕后再执行其后的代码,timeout代表超时时间表示等待的时间
3.p.terminate()立即结束子进程
4.process子类创建子进程

from multiprocessing import Process import time import os #继承Process类 class Process_Class(Process): #因为Process类本身也有__init__方法,这个子类相当于重写了这个方法, #但这样就会带来一个问题,我们并没有完全的初始化一个Process类,所以就不能使用从这个类继承的一些方法和属性, #最好的方法就是将继承类本身传递给Process.__init__方法,完成这些初始化操作 def __init__(self,interval): Process.__init__(self) self.interval = interval #重写了Process类的run()方法 def run(self): print("子进程(%s) 开始执行,父进程为(%s)"%(os.getpid(),os.getppid())) t_start = time.time() time.sleep(self.interval) t_stop = time.time() print("(%s)执行结束,耗时%0.2f秒"%(os.getpid(),t_stop-t_start)) if __name__=="__main__": t_start = time.time() print("当前程序进程(%s)"%os.getpid()) p1 = Process_Class(2) #对一个不包含target属性的Process类执行start()方法,就会运行这个类中的run()方法,所以这里会执行p1.run() p1.start() p1.join() t_stop = time.time() print("(%s)执行结束,耗时%0.2f"%(os.getpid(),t_stop-t_start))
五、使用进程池创建子进程pool
1.当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态成生多个进程,但如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以用到multiprocessing模块提供的Pool方法。初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来执行

from multiprocessing import Pool import os,time,random def worker(msg): t_start = time.time() print("%s开始执行,进程号为%d"%(msg,os.getpid())) #random.random()随机生成0~1之间的浮点数 time.sleep(random.random()*2) t_stop = time.time() print(msg,"执行完毕,耗时%0.2f"%(t_stop-t_start)) po=Pool(3) #定义一个进程池,最大进程数3 for i in range(0,10): #Pool.apply_async(要调用的目标,(传递给目标的参数元祖,)) #每次循环将会用空闲出来的子进程去调用目标 po.apply_async(worker,(i,)) print("----start----") po.close() #关闭进程池,关闭后po不再接收新的请求 po.join() #等待po中所有子进程执行完成,必须放在close语句之后 print("-----end-----") #结果 ----start---- 0开始执行,进程号为21466 1开始执行,进程号为21468 2开始执行,进程号为21467 0 执行完毕,耗时1.01 3开始执行,进程号为21466 2 执行完毕,耗时1.24 4开始执行,进程号为21467 3 执行完毕,耗时0.56 5开始执行,进程号为21466 1 执行完毕,耗时1.68 6开始执行,进程号为21468 4 执行完毕,耗时0.67 7开始执行,进程号为21467 5 执行完毕,耗时0.83 8开始执行,进程号为21466 6 执行完毕,耗时0.75 9开始执行,进程号为21468 7 执行完毕,耗时1.03 8 执行完毕,耗时1.05 9 执行完毕,耗时1.69 -----end-----
2.apply_async(非阻塞式) apply(阻塞式):必须等上一个任务执行完成后才能执行下一个
3.进程池中的异步

from multiprocessing import Pool import time import os def test(): print("---进程池中的进程---pid=%d,ppid=%d--"%(os.getpid(),os.getppid())) for i in range(3): print("----%d---"%i) time.sleep(1) return "hahah" def test2(args): print("---callback func--pid=%d"%os.getpid()) print("---callback func--args=%s"%args) pool = Pool(3) pool.apply_async(func=test,callback=test2) time.sleep(5) print("----主进程-pid=%d----"%os.getpid())
六、使用queue完成进程间通信
1.queue队列的导入:from multiprocessing import queue
2.实例化queue:q = Queue(int),初始化Queue()对象时(例如:q=Queue()),若括号中没有指定最大可接收的消息数量,或数量为负值,那么就代表可接受的消息数量没有上限(直到内存的尽头)
3.Queue.qsize():返回当前队列包含的消息数量;
4.Queue.empty():如果队列为空,返回True,反之False
5.Queue.full():如果队列满了,返回True,反之False
6.Queue.get([block[, timeout]]):获取队列中的一条消息,然后将其从列队中移除,block默认值为True
1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果为空,此时程序将被阻塞(停在读取状态),直到从消息列队读到消息为止,如果设置了timeout,则会等待timeout秒,若还没读取到任何消息,则抛出"Queue.Empty"异常;
2)如果block值为False,消息列队如果为空,则会立刻抛出"Queue.Empty"异常;
7.Queue.get_nowait():相当Queue.get(False)
8.Queue.put(item,[block[, timeout]]):将item消息写入队列,block默认值为True
1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果已经没有空间可写入,此时程序将被阻塞(停在写入状态),直到从消息列队腾出空间为止,如果设置了timeout,则会等待timeout秒,若还没空间,则抛出"Queue.Full"异常;
2)如果block值为False,消息列队如果没有空间可写入,则会立刻抛出"Queue.Full"异常;
9.Queue.put_nowait(item):相当Queue.put(item, False)
六、进程池中的queue
1.在进程池中使用queqe需要先引入manager模块(from multiprocessing import Manager),然后用Manager创建queue队列 q = Manager().Queue()