Python之多进程Process间通信

本文深入探讨了Python中multiprocessing模块的进程间通信机制,详细介绍了队列和管道两种通信方式的使用方法,以及如何利用它们在多进程中进行数据交换。

multiprocessing 支持进程之间的两种通信通道:1.队列;2.管道

前:Process的一些方法:

-name:进程的名称。该名称是一个字符串,仅用于识别目的。它没有语义。可以为多个进程指定相同的名称。

-is_alive():返回进程是否还活着。

-pid:返回进程ID。在生成该进程之前,这将是 None 。

-terminate():终止进程。 在Unix上,这是使用 SIGTERM 信号完成的;在Windows上使用 TerminateProcess() 。 请注意,不会执行退出处理程序和finally子句等。

请注意,进程的后代进程将不会被终止 —— 它们将简单地变成孤立的。

-kill():与 terminate() 相同,但在Unix上使用 SIGKILL 信号。

 

Queue 类是一个近似 queue.Queue 的克隆,队列是线程和进程安全的;

Pipe() 函数返回一个由管道连接的连接对象,默认情况是双工,返回的两个连接对象 Pipe() 表示管道的两端conn1,conn2。

每个连接对象都有 send() 和 recv() 方法(相互之间的)。请注意,如果两个进程(或线程)同时尝试读取或写入管道的 同一 端,则管道中的数据可能会损坏。当然,同时使用管道的不同端的进程不存在损坏的风险;

mutilprocessing.queue中常见方法:

-put(obj[, block[, timeout]]):将 obj 放入队列。如果可选参数 block 是 True (默认值) 而且 timeout 是 None (默认值), 将会阻塞当前进程,直到有空的缓冲槽。如果 timeout 是正数,将会在阻塞了最多 timeout 秒之后还是没有可用的缓冲槽时抛出 queue.Full  异常。反之 (block 是 False 时),仅当有可用缓冲槽时才放入对象,否则抛出 queue.Full 异常 (在这种情形下 timeout 参数会被忽略)。

-get([block[, timeout]]):从队列中取出并返回对象。如果可选参数 block 是 True (默认值) 而且 timeout 是 None (默认值), 将会阻塞当前进程,直到队列中出现可用的对象。如果 timeout 是正数,将会在阻塞了最多 timeout 秒之后还是没有可用的对象时抛出 queue.Empty 异常。反之 (block 是 False 时),仅当有可用对象能够取出时返回,否则抛出 queue.Empty 异常 (在这种情形下 timeout 参数会被忽略)。

Queue队列实现进程通信:

# -*- coding: UTF-8 -*-
from multiprocessing import Process,Queue
import os,time,random

#写数据进程函数
def proc_write(q,urls):
    print('Writing....')
    for url in urls:
        q.put(url)
        print('put %s to msg_queue' % url)
        time.sleep(random.randint(2,5))

#读数据进程函数
def proc_read(q):
    print('reading...')
    i=0
    while True:
        url = q.get(True)
        print('Get %s from msg_queue' % url)
        i+=1

if __name__ == '__main__':
    msg_q = Queue()
    proc_write1 = Process(target=proc_write,args=(msg_q,['url_1','url_2','url_3']))
    proc_write2 = Process(target=proc_write,args=(msg_q,['msg_1','msg_2']))
    proc_read1 = Process(target=proc_read,args=(msg_q,))
    #启动
    proc_write1.start()
    proc_write2.start()
    proc_read1.start()
    #等待结束
    proc_write1.join()
    proc_write2.join()

Pipe实现进程通信:

# -*- coding: UTF-8 -*-
import multiprocessing
import os,time,random

#写数据进程执行的代码
def proc_send(pipe,urls):
    #print 'Process is write....'
    for url in urls:
        print('sending :%s' %url)
        pipe.send(url)
        time.sleep(random.random())



#读数据进程的代码
def proc_recv(pipe):
    while True:
        print('rev:%s' %pipe.recv())
        time.sleep(random.random())

if __name__ == '__main__':
    #父进程创建pipe,并传给各个子进程
    pipe = multiprocessing.Pipe()
    p1 = multiprocessing.Process(target=proc_send,args=(pipe[0],['url_'+str(i) for i in range(10) ]))
    p2 = multiprocessing.Process(target=proc_recv,args=(pipe[1],))
    #启动子进程,写入
    p1.start()
    p2.start()

    p1.join()
    p2.terminate()

附加:sigterm,sigkill,sigint区别:

信号产生方式对进程的影响
sigint通过ctrl+c将会对当进程发送此信号信号被当前进程树接收到,也就是说,不仅当前进程会收到信号,它的子进程也会收到
sigtermkill命令不加参数就是发送这个信号只有当前进程收到信号,子进程不会收到。如果当前进程被kill了,那么它的子进程的父进程将会是init,也就是pid为1的进程

在这三个信号中,sigkill是不能被捕获的,程序收到这个信号后,一定会退出。这就是kill -9一定能保证将程序杀死的原因

SIGTERM比较友好,进程能捕捉这个信号,根据您的需要来关闭程序。在关闭程序之前,您可以结束打开的记录文件和完成正在做的任务。在某些情况下,假 如进程正在进行作业而且不能中断,那么进程可以忽略这个SIGTERM信号。程序捕获SIGTERM信号进行处理,不一定会退出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值