目录
4.使用multiprocessing.Manager().list或dict
Python多进程利用multiprocessing模块,创建独立进程并行计算,突破GIL限制,适合CPU密集型任务。
(1)如何创建
用multiprocessing模块
import os
import multiprocessing
import time
def info(title):
print(title)
print(__name__)
print("father ppid", os.getppid()) # 父进程id
print("self pid", os.getpid()) # 子进程id
print("-----------")
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 time
def 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 os
def 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 multiprocessing
def 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 os
datalist = [] #全局变量
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 time
def 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 multiprocessing
def func(num):
num.value = 10.78
if __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 multiprocessing
def 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 time
def func(mydict, mylist):
mydict["id"] = 54321
mydict["name"] = "python"
mylist.append("李四")
if __name__ == "__main__":
mydict = multiprocessing.Manager().dict()
mylist = multiprocessing.Manager().list()
mydict["id"] = 12345
mylist.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 random
class Piao(Process):
def __init__(self,name):
self.name=name
super().__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)进程间通信
end