python多进程
Python多进程利用multiprocessing模块,创建独立进程并行计算,突破GIL限制,适合CPU密集型任务。
(1)如何创建
用multiprocessing模块
import os
import multiprocessing
import timedef info(title):print(title)print(__name__)print("father ppid", os.getppid()) # 父进程idprint("self pid", os.getpid()) # 子进程idprint("-----------")print("执行被调用函数中.......")time.sleep(5)if __name__ == "__main__":info("hello")#创建多进程p = multiprocessing.Process(target = info, args = ("apple",))p.start()p.join() #父亲进程必须等待子进程干完活,执行后续代码print("继续执行父进程")
(2)join函数
join的作用:此子进程执行完后才会执行父进程
注意事项:默认主进程的结束不会影响子进程,join函数的作用是主进程要等子进程结束了才继续运行
import os
import multiprocessing
import timedef info(title):print(title)time.sleep(2)print(__name__)print("father ppid", os.getppid())print("self pid", os.getpid())print("-----------")if __name__=="__main__":p1 = multiprocessing.Process(target=info, args=("A1",))p2 = multiprocessing.Process(target=info, args=("A2",))p3 = multiprocessing.Process(target=info, args=("A3",))p1.start() # 并发干活p2.start()p3.start()p1.join()p2.join()p3.join()# 等子进程执行完后再执行父进程print("all over")'''# 进程轮流干活p1.start()p1.join()p2.start()p2.join()p3.start()p3.join()'''
(3)锁
用multiprocessing.RLock
import os
import multiprocessing
import time# 多进程,并发,乱序并发执行,容易出错
# 多进程加锁,挨个执行,解决出错,不过执行顺序仍然是乱序def showdata(lock, i): #将锁作为函数参数time.sleep(5)with lock:print(i)if __name__ == "__main__":lock = multiprocessing.RLock() #创建锁for num in range(10):multiprocessing.Process(target=showdata, args=(lock, num)).start() #匿名对象
(4)管道
这里用用multiprocessing.Pipe,创建管道可用于进程间通信。
创建的管道有两个口,管道的一个口只能在一个进程中使用,不能用同一个口在一个进程发消息,在另一个进程接受消息。
注意管道的口两个都要被使用才行。
import multiprocessing
import time
import osdef showdata(conn): #conn类型conn.send("发送的数据a") #发送的数据print(os.getpid(), conn.recv(), time.time()) #收到的数据conn.close() #关闭if __name__ == "__main__":conn_a, conn_b = multiprocessing.Pipe() #创建一个管道,两个口# print(id(conn_a),id(conn_b))# print(type(conn_a), type(conn_b))p = multiprocessing.Process(target=showdata, args=(conn_a,))p.start()conn_b.send("要发送的数据b")print(os.getpid(), conn_b.recv(), time.time())conn_b.close()
(5)队列
这里用multiprocessing.Queue,进程进程间通信。
使用队列传输数据时,父进程和子进程都可以put数据,但当其中一个进程put数据成功时,另一个进程put数据就会失败
因此单项通信:要么①父进程插入,子进程读取;要么②子进程写入,父进程读取
import multiprocessingdef func(queue):print(id(queue))queue.put("子进程加入数据")#print(queue.get())if __name__ == "__main__":myqueue = multiprocessing.Queue()p = multiprocessing.Process(target=func, args=(myqueue,))p.start()#myqueue.put("主进程加入数据")print(myqueue.get())
(6)多进程中普通全局变量无法共享
在多进程中,普通的全局变量不会被共享
import multiprocessing
import time
import osdatalist = [] #全局变量def adddata(datalist):datalist.append(1)datalist.append(2)datalist.append(3)print(os.getpid(), os.getppid(), datalist, time.time())if __name__ == "__main__":p = multiprocessing.Process(target=adddata, args=(datalist,))p.start()time.sleep(2)datalist.append("a")datalist.append("b")datalist.append("c")print(os.getpid(), os.getppid(), datalist, time.time())
(7)进程间数据共享
1.使用multiprocessing.Queue()
import multiprocessing
import os
import timedef adddata(queue, i):#time.sleep(2) #说明父进程会等待子进程执行完毕后再执行queue.put(i)print("put", i, os.getppid(), os.getpid(), time.time())if __name__ == "__main__":queue = multiprocessing.Queue() # 队列可以实现共享-单向mylist = []for i in range(10): #创建10个进程p = multiprocessing.Process(target=adddata, args=(queue, i))p.start()#print("queue.get()", queue.get()) # 加入此语句会程序会卡在put 0#time.sleep(2)mylist.append(queue.get())print(mylist)
2.使用multiprocessing.Value
import multiprocessingdef func(num):num.value = 10.78if __name__ == "__main__":num = multiprocessing.Value("d", 10.0) # d表示数类型,可以多个进程之间共享print(num.value)p = multiprocessing.Process(target=func, args=(num,))p.start()p.join() #不要此语句会有变化print(num.value)
3.使用multiprocessing.Array
个人感觉使用array不太方便
import multiprocessingdef func(array):array[2] = 9999#array.append(888) #没有append方法if __name__ == "__main__":myarray = multiprocessing.Array("i", [1, 2, 3, 4, 5])print(myarray[:])p = multiprocessing.Process(target=func, args=(myarray,))p.start()p.join()print(myarray[:])
4.使用multiprocessing.Manager().list或dict
import multiprocessing
import timedef func(mydict, mylist):mydict["id"] = 54321mydict["name"] = "python"mylist.append("李四")if __name__ == "__main__":mydict = multiprocessing.Manager().dict()mylist = multiprocessing.Manager().list()mydict["id"] = 12345mylist.append("张三")print(mydict, mylist)p = multiprocessing.Process(target=func, args=(mydict, mylist))p.start()p.join() #注意此语句的重要性# 没有此语句,父进程会在子进程活未干完的情况下继续执行,可能导致冲突#time.sleep(5)print(mydict, mylist)
(8)守护进程
主进程创建守护进程
其一:守护进程会在主进程代码执行结束后就终止
其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allowed to have children
注意:进程之间是互相独立的,主进程代码运行结束,守护进程随即终止
from multiprocessing import Process
import time
import randomclass Piao(Process):def __init__(self,name):self.name=namesuper().__init__()def run(self):print('%s is piaoing' %self.name)time.sleep(random.randrange(1,3))print('%s is piao end' %self.name)p=Piao('egon')
p.daemon=True #一定要在p.start()前设置,设置p为守护进程,禁止p创建子进程,并且父进程代码执行结束,p即终止运行
p.start()
print('主')
(9)进程信号量
同线程一样,信号量为1就相当于锁。
(10)进程间通信
参考:python进程间通信-CSDN博客
end