Python3基础-进程间通讯

multiprocessing包是Python中的多进程管理包。
与threading.Thread类似,它可以利用multiprocessing.Process对象来创建一个进程。
该进程可以运行在Python程序内部编写的函数。
该Process对象与Thread对象的用法相同,也有start(), run(), join()的方法。
此外multiprocessing包中也有Lock/Event/Semaphore/Condition类 
(这些对象可以像多线程那样,通过参数传递给各个进程),用以同步进程,其用法与threading包中的同名类一致。
所以,multiprocessing的很大一部份与threading使用同一套API,只不过换到了多进程的情境
from multiprocessing import Process
import time
def f(name):
    time.sleep(1)
    print('hello', name,time.ctime())

if __name__ == '__main__':
    p_list=[]
    for i in range(3):
        p = Process(target=f, args=('alvin',))
        p_list.append(p)
        p.start()
    for i in p_list:
        p.join()
    print('end')
多进程调用1
from multiprocessing import Process
import time

class MyProcess(Process):
    def __init__(self):
        super(MyProcess, self).__init__()
        #self.name = name

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


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')
多进程调用2
构造方法:

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:进程号。
from multiprocessing import Process
import time

class MyProcess(Process):
    def __init__(self):
        super(MyProcess, self).__init__()
        #self.name = name

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


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

    # for p in p_list:
    #     p.join()

    print('end')
====================
结果输出
end
daemon
from multiprocessing import Process
import os
import time


def info(title):
    print("title:", title)
    print('parent process:', os.getppid())
    print('process id:', os.getpid())


def f(name):
    info('function f')
    print('hello', name)


if __name__ == '__main__':
    info('main process line')
    time.sleep(1)
    print("------------------")
    p = Process(target=info, args=('yuan',))
    p.start()
    p.join()

输出结果如下:

title: main process line
parent process: 13796
process id: 2624
------------------
title: yuan
parent process: 2624
process id: 13512

 

os.getpid()

  1. 功能:获取一个进程的PID值
  2. 返回值:返回当前进程的PID

os.getppid()

  1. 功能:获取父进程的PID值
  2. 返回值:返回父进程PID

os._exit(status)

  1. 功能:结束一个进程
  2. 参数:进程的终止状态(随便输一个整数,eg:0,代表结束状态)

sys.exit([status])

  1. 功能:退出进程
  2. 参数:
    1. 整数:表示退出状态
    2. 字符串:表示退出时,打印内容

 ############进程间通信

不同进程间内存是不共享的,要想实现两个进程间的数据交换,可以用多进程里的Queue来解决

Queues

使用方法跟threading里的queue差不多,注意在执行的时候,queue是一个备份,而不是原来的queue,不过实现了数据共享

#进程间通讯
from multiprocessing import Process, Queue
#import queue

def f(q,n):
    #q.put([123, 456, 'hello'])
    q.put(n*n+1)
    #print("q===is",q.get())
    print("son process",id(q))

if __name__ == '__main__':
    q = Queue()  #try: q=queue.Queue()
    print("main process",id(q))
    #print("q ===is:",q.get())

    for i in range(3):
        #print("i===",i)
        p = Process(target=f, args=(q,i))
        '''实现主进程和子进程的同学,放入同一个队列中'''
        p.start()

    print("get的内容是",q.get())
    print("get的内容是",q.get())
    print("get的内容是",q.get())

Pipe管道

和队列的功能差不多,实现两个进程之前数据的传递

from multiprocessing import Process, Pipe

def f(conn):
    conn.send([12, {"name":"yuan"}, 'hello'])
    response=conn.recv()
    print("response",response)
    print("q_ID2:", id(conn))
    conn.close()

if __name__ == '__main__':

    parent_conn, child_conn = Pipe() #管道会产生两个返回值
    print("q_ID1:",id(child_conn))
    p = Process(target=f, args=(child_conn,)) #创建一个子进程
    p.start()
    print(parent_conn.recv())   # 收到  [12, {"name":"yuan"}, 'hello']
    parent_conn.send("你好!") # 发送  您好!
    p.join()

Manager 管道

上面两种都是实现数据传递,并没有实现数据共享,即一个进程去更改另一个进程的数据

现在实现数据共享

可实现的数据类型很多:list、dict、Namespace、Locl、 RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value and Array

写法1

from multiprocessing import Process, Manager


def f(d, l,i):
    d[1] = '1'
    d['2'] = 2
    l.append(i)  # 追加一个i
    # print(l)


if __name__ == '__main__':
    d = Manager().dict()  # 生成一个字典,可在多个进程间共享和传递
    l = Manager().list(range(5))  # 列表
    print("初始字典",d)
    print("初始列表",l)

    p_list = []  # 进程列表
    for i in range(10):
        p = Process(target=f, args=(d, l, i))  # 循环10次每次创建一个进程
        p.start()
        p_list.append(p)  # 加入进程列表里

    for res in p_list:  # 等所有进程结束
        res.join()

    print(d)
    print(l)

  写法2

from multiprocessing import Process, Manager


def f(d, l,i):
    d[1] = '1'
    d['2'] = 2
    l.append(i)  # 追加一个i
    # print(l)


if __name__ == '__main__':
    with Manager() as manager:
        d = manager.dict()
        l = manager.list(range(5))
        print("初始字典",d)
        print("初始列表",l)

        p_list = []  # 进程列表
        for i in range(10):
            p = Process(target=f, args=(d, l, i))  # 循环10次每次创建一个进程
            p.start()
            p_list.append(p)  # 加入进程列表里

        for res in p_list:  # 等所有进程结束
            res.join()

        print(d)
        print(l)

执行结果如下:

初始字典 {}
初始列表 [0, 1, 2, 3, 4]
{1: '1', '2': 2}
[0, 1, 2, 3, 4, 0, 1, 3, 2, 4, 5, 6, 7, 8, 9]

 

posted @ 2020-09-15 17:44  槑槑DE  阅读(117)  评论(0)    收藏  举报