multiprocessing模块

multiprocessing模块

由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。
multiprocessing包是Python中的多进程管理包。与threading.Thread类似,它可以利用multiprocessing.Process对象来创建一个进程。该进程可以运行在Python程序内部编写的函数。该Process对象与Thread对象的用法相同,也有start(), run(), join()的方法。此外multiprocessing包中也有Lock/Event/Semaphore/Condition类 (这些对象可以像多线程那样,通过参数传递给各个进程),用以同步进程,其用法与threading包中的同名类一致。所以,multiprocessing的很大一部份与threading使用同一套API,只不过换到了多进程的情境。

process

构造方法:

Process([group [, target [, name [, args [, kwargs]]]]])

group:线程组,目前还没有实现,库引用中提示必须是None;

target:要执行的方法

name:进程名

args/kwargs:要传入方法的参数

实例方法:

is_alive():返回进程是否在运行

join([timeout]):阻塞当前上下文环境的进程程,直到调用此方法的进程终止或到达指定的timeout(可选参数)。
 
start():进程准备就绪,等待CPU调度

run():strat()调用run方法,如果实例进程时未制定传入target,这star执行t默认run()方法。
 

terminate():不管任务是否完成,立即停止工作进程

属性

daemon:和线程的setDeamon功能一样守护进程

name:进程名字。

pid:进程号。

  • Python的进程调用
from multiprocessing import Process
import time
def foo(q):
    time.sleep(1)
    print(q)

if __name__=="__main__":

    l=[]
    for i in range(3):

        p=Process(target=foo,args=("W"))
        l.append(p)
        p.start()
    for i in l:
        i.join()
    print("end")

"D:Program Filespython.exe" E:/py_code/进程队列/进程队列.py
W
W
W
end

Process finished with exit code 0

上述进程的调用是比较常规的调用。

  • Proscess继承类
from multiprocessing import Process
import time
class MyProcess(Process):
    def __init__(self):
        super(MyProcess, self).__init__()
        # self.name = name

    def run(self):

        print ('hello', self.name,time.ctime())
        time.sleep(1)


if __name__ == '__main__':
    p_list=[]
    for i in range(3):
        p = MyProcess()
        p.start()
        p_list.append(p)
    for p in p_list:
        p.join()
    print('end')


"D:Program Filespython.exe" E:/py_code/进程队列/进程队列.py
hello alvin:1 Thu Jul 20 18:07:56 2017
hello alvin:0 Thu Jul 20 18:07:56 2017
hello alvin:2 Thu Jul 20 18:07:56 2017
end

Process finished with exit code 0




上面的代码定义了一个类并继承了一个进程,并开启了5个进程,这5个进程会均会执行MyProcess类中的run方法即打印 ('hello',self.name,time.ctime())。

  • 进程间的通讯(Queue)
from multiprocessing import Process,Queue
import queue

def foo(q):
    q.put("1")

def bar(q):

    print(q.get(),"ok")

if __name__=="__main__":
    q=Queue()  #相等于q=queue.Queue()
    for i in range(3):
        p=Process(target=foo,args=(q,))

        p1=Process(target=bar,args=(q,))
        p1.start()
        p.start()

"D:Program Filespython.exe" E:/py_code/进程队列/进程队列.py
1 ok
1 ok
1 ok

Process finished with exit code 0
  • 管道(pipe)

管道()函数返回由管道连接的一对连接对象,该管道默认是双向的(双向的)。例如:

def foo(o):
    data=o.recv()
    print(data)
    o.send("hey!whatmini")



if __name__=="__main__":
    sock,conn=Pipe()#sock与conn相当于管道的两个接口
#
    t1=Process(target=foo,args=(conn,))
    t1.start()
    sock.send("你好")  
    print(sock.recv())
    

"D:Program Filespython.exe" E:/py_code/进程队列/进程队列.py
你好
hey!whatmini

Process finished with exit code 0

    
    

需要注意的是:Pipe()返回的两个连接对象代表管道的两端。 每个连接对象都有send()和recv()方法(等等)。 请注意,如果两个进程(或线程)尝试同时读取或写入管道的同一端,管道中的数据可能会损坏

manager

Queue和pipe只是实现了数据交互,并没实现数据共享,即一个进程去更改另一个进程的数据。

from multiprocessing import Process, Manager

def foo(l,i):
    l.append(i*i)

if __name__ == '__main__':

    with Manager() as manager:

        manager=Manager()

        l = manager.list([11,22,33])  #创建一个列表也可以字典类型都支持
        p_list = []
        for i in range(10):
            p = Process(target=foo, args=(l,i))
            p.start()
            p_list.append(p)

        for res in p_list:
            res.join()

        print(l)

"D:Program Filespython.exe" E:/py_code/进程队列/进程队列.py
[11, 22, 33, 4, 1, 9, 36, 81, 0, 49, 16, 64, 25]

Process finished with exit code 0
进程池

进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。

from multiprocessing import Pool   #
import time

def foo(args):
 time.sleep(1)
 print(args)

if __name__ == '__main__':
 p = Pool(5)   #进程池对象的最大量为5个
 for i in range(30):  #30个任务5个进程对象去执行
     p.apply_async(func=foo, args= (i,))  #异步执行

 p.close()   # 等子进程执行完毕后关闭线程池
 # time.sleep(2)
 # p.terminate()  # 立刻关闭线程池
 p.join()  #主进程等待所有子进程执行完毕,必须在close或terminate之后
 

进程池内部维护一个进程序列,当使用时,去进程池中获取一个进程,如果进程池序列中没有可供使用的进程,那么程序就会等待,直到进程池中有可用进程为止。

进程池中有以下几个主要方法:

1 apply:从进程池里取一个进程并执行

2 apply_async:apply的异步版本

3 terminate:立刻关闭线程池

4 join:主进程等待所有子进程执行完毕,必须在close或terminate之后

6 close:等待所有进程结束后,才关闭线程池

原文地址:https://www.cnblogs.com/lijian-22huxiaoshan/p/7215279.html