多进程(multiprocessing)

import multiprocessing
import os, time


def info(title):
    print(title)
    # time.sleep(1)
    print("Module name:", __name__)
    print("Parent process id:", os.getppid())   #父进程id
    print("Current process id:", os.getpid())  #当前进程id
    print("\n\n")

# if __name__ == "__main__":     #启动一个子进程
#     info("Main process")
#     p = multiprocessing.Process(target=info, args=('Child process',))
#     p.start()

if __name__ == "__main__":     #启动多个子进程(查看结果)
    info("Main process")
    for i in range(10):
        p = multiprocessing.Process(target=info, args=('Child process %s' %i,))
        p.start()

注意:由于进程之间的数据需要各自持有一份,所以创建进程需要的非常大的开销。

进程间通信

不同进程之间内存是不共享的,要想实现两个进程间的数据交换,有以下方法:

进程队列(Queue)

使用方法跟threading里的queue差不多(进程Queue使用pickle数据传递)

import multiprocessing, time

def put_func(qq):
    qq.put([12, None, "hello"])
    # time.sleep(2)
    # print("put:",qq.qsize())

def get_func(qq):
    print(qq.get())

if __name__ == "__main__":
    q = multiprocessing.Queue()         #创建一个进程Queue对象
    puter = multiprocessing.Process(target=put_func,args=(q,))    #将Queue对象传递到新创建的子进程中
    puter.start()

    geter = multiprocessing.Process(target=get_func, args=(q,))
    geter.start()
Pipe

pipe()返回一对连接对象,conn1, conn2代表了pipe的两端。每个对象都有send()和recv()方法。

from multiprocessing import Pipe,Process
import time

# a_conn, b_conn = Pipe()
# a_conn.send(['a', 'f', 'e'])
# print(b_conn.recv())

def f(conn):
    time.sleep(2)
    conn.send(['a', 'b', 'c'])

def ff(conn):
    print(conn.recv())

if __name__ == "__main__":
    conn1, conn2 = Pipe()
    p1 = Process(target=f, args=(conn2,))
    p2 = Process(target=ff ,args=(conn1,))
    # p1.daemon = True    # 加上daemon属性
    # p2.daemon = True
    p1.start()
    p2.start()
Manager

Python实现多进程间通信的方式有很多种,例如队列,管道等。但是这些方式只适用于多个进程都是源于同一个父进程的情况。如果多个进程不是源于同一个父进程,只能用共享内存,信号量等方式,但是这些方式对于复杂的数据结构,例如Queue,dict,list等,使用起来比较麻烦,不够灵活。
Manager是一种较为高级的多进程通信方式,它能支持Python支持的的任何数据结构。
它的原理是:先启动一个ManagerServer进程,这个进程是阻塞的,它监听一个socket,然后其他进程(ManagerClient)通过socket来连接到ManagerServer,实现通信。

from multiprocessing import Process, Manager
import os

def f(d, l):
    d[os.getpid()] = os.getpid()
    d[1] = '1'
    l.append(os.getpid())
    print(l)

if __name__ == "__main__":
    with Manager() as manager:    #manager = multiprocessing.Manager()
        d = manager.dict()          ## 生成一个可在多个进程间共享和传递的字典
        l = manager.list(range(5))  ##生成一个可在多个进程间共享和传递的列表

        p_list = []
        for i in range(10):
            p = Process(target=f, args=(d, l))
            p.start()
            p_list.append(p)
        for res in p_list:
            res.join()

        print(d)
        print(l)

进程池

进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。进程池设置最好等于CPU核心数量

进程池中有两个方法:
• apply 串行
• apply_async

from multiprocessing import Process, Pool
import time, os

def Foo(i):
    time.sleep(2)
    return  i+100

def Bar(arg):
    print(os.getpid())    #使用的主进程做的回调(os.getpid()值是一样的)
    print(arg)


if __name__ == '__main__':
    pool = Pool(3)       #进程池同时可放3个进程
    for i in range(10):
        # pool.apply(func=Foo, args=(i,))
        pool.apply_async(func=Foo, args=(i,), callback=Bar)  #callback回调,func执行完毕后执行回调函数,注意:使用的主进程做的回调

    print('end')
    pool.close()   # 一定要先关闭进程池再join
    pool.join()  #进程池中的进程执行完毕后再关闭,如果注释,程序就直接关闭了

你可能感兴趣的:(多进程(multiprocessing))