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将会对当进程发送此信号 | 信号被当前进程树接收到,也就是说,不仅当前进程会收到信号,它的子进程也会收到 |
| sigterm | kill命令不加参数就是发送这个信号 | 只有当前进程收到信号,子进程不会收到。如果当前进程被kill了,那么它的子进程的父进程将会是init,也就是pid为1的进程 |
在这三个信号中,sigkill是不能被捕获的,程序收到这个信号后,一定会退出。这就是kill -9一定能保证将程序杀死的原因
SIGTERM比较友好,进程能捕捉这个信号,根据您的需要来关闭程序。在关闭程序之前,您可以结束打开的记录文件和完成正在做的任务。在某些情况下,假 如进程正在进行作业而且不能中断,那么进程可以忽略这个SIGTERM信号。程序捕获SIGTERM信号进行处理,不一定会退出。
本文深入探讨了Python中multiprocessing模块的进程间通信机制,详细介绍了队列和管道两种通信方式的使用方法,以及如何利用它们在多进程中进行数据交换。

387

被折叠的 条评论
为什么被折叠?



