python多进程

发布于:2025-05-28 ⋅ 阅读:(20) ⋅ 点赞:(0)

目录

(1)如何创建

(2)join函数

(3)锁

(4)管道

(5)队列

(6)多进程中普通全局变量无法共享

(7)进程间数据共享

1.使用multiprocessing.Queue() 

2.使用multiprocessing.Value

3.使用multiprocessing.Array

4.使用multiprocessing.Manager().list或dict

(8)守护进程

(9)进程信号量

(10)进程间通信


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)进程间通信

参考:python进程间通信-CSDN博客


end


网站公告

今日签到

点亮在社区的每一天
去签到