Python 如何检测多处理。管道已满?
问题描述:我正在用Python进行多处理,并使用multiprocessing.Pipe()在进程之间进行通信。我已经搜索了很多,但仍然找不到一种方法来检测管道是否已满。例如,WritePie进程不断地将数字放入两个不同的管道(奇数和偶数),readPipe进程不断地从这两个管道读取。但是,从奇数管道读取数据的速度要快得多,因此偶数管道将充满数据。此时,WritePie进程将被阻塞,而readPipe进程仍在等待从奇数管道读取,这将导致死锁 我的问题:是否有任何方法可以检测到管道已满,这样我们就可以在管道仍在运行时停止将数字放入满管道,并将数字放入仍有空间的管道Python 如何检测多处理。管道已满?,python,python-3.x,ipc,python-multiprocessing,Python,Python 3.x,Ipc,Python Multiprocessing,问题描述:我正在用Python进行多处理,并使用multiprocessing.Pipe()在进程之间进行通信。我已经搜索了很多,但仍然找不到一种方法来检测管道是否已满。例如,WritePie进程不断地将数字放入两个不同的管道(奇数和偶数),readPipe进程不断地从这两个管道读取。但是,从奇数管道读取数据的速度要快得多,因此偶数管道将充满数据。此时,WritePie进程将被阻塞,而readPipe进程仍在等待从奇数管道读取,这将导致死锁 我的问题:是否有任何方法可以检测到管道已满,这样我们就
from multiprocessing import Process, Pipe
def writePipe(sendNumberOdd, sendNumberEven):
i = 0
while True:
if i % 2 == 0:
sendNumberEven.send(i)
else:
sendNumberOdd.send(i)
i += 1
def readPipe(recvNumberOdd, recvNumberEven):
countEven = 0
while True:
countEven += 1
print(countEven, recvNumberEven.recv())
countOdd = 0
while countOdd < 50:
countOdd += 1
print (countOdd, recvNumberOdd.recv())
if __name__ == '__main__':
recvNumberOdd, sendNumberOdd = Pipe(duplex=False)
recvNumberEven, sendNumberEven = Pipe(duplex=False)
write = Process(target=writePipe, args=(sendNumberOdd, sendNumberEven))
read = Process(target=readPipe, args=(recvNumberOdd, recvNumberEven))
write.start()
read.start()
sendNumberOdd.close()
sendNumberEven.close()
来自多处理导入进程的管道
def WritePie(SendNumberId,SendNumberReven):
i=0
尽管如此:
如果i%2==0:
SendNumberReven.send(一)
其他:
sendnumberd.send(i)
i+=1
def读取管道(RecvNumber奇数、RecvNumber偶数):
偶数=0
尽管如此:
偶数+=1
打印(countEven,recvNumberEven.recv())
count奇数=0
当countOdd<50时:
count奇数+=1
打印(countOdd,recvNumberOdd.recv())
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
recvNumberOdd,sendNumberOdd=管道(双工=假)
RECVNUMBEREEN,sendNumberEven=管道(双工=假)
write=Process(target=writepe,args=(sendNumberOdd,sendNumberEven))
read=Process(target=readPipe,args=(recvNumberOdd,recvnumber偶数))
write.start()
read.start()
sendnumberdd.close()
sendNumberEven.close()
未经测试的提案
class Connection(multiprocessing.Connection):
def __init__(self, maxsize=0):
self.__maxsize = maxsize
self.size = 0
self.__lock = multiprocessing.Lock
def send(self, obj):
with self.__lock:
self.size += sizeof(obj)
super().send(obj)
def recv(self):
_recv = super().recv()
with self.__lock:
self.size -= sizeof(_recv)
return _recv
def full(self):
if self.__maxsize > 0:
return self.size >= self.__maxsize
return None
def Pipe(maxsize=0, duplex=True):
return Connection(maxsize), Connection(maxsize)
执行
poll()
检查是否有数据准备就绪
Python»文档:
例如:
if recvNumberEven.poll():
countEven += 1
print(countEven, recvNumberEven.recv())
对于这两种情况,可选择使用wait(…)
您可以使用选择
模块中的功能来执行输出管道是否已满的测试
import select
import multiprocessing.connection as mpc
def pipe_full(conn):
r, w, x = select.select([], [conn], [], 0.0)
return 0 == len(w)
i, o = mpc.Pipe(duplex=False)
n = 0
while not pipe_full(o):
o.send(n)
n += 1
print('{} items fit.'.format(n))
谢谢你的回答。然而,我认为你误解了我的问题。我需要的是一种检测管道是否已满的方法,以停止从WritePie进程向管道发送更多数据,从而防止死锁。同时,poll()只能用于知道管道中是否有任何数据要读取,因此在这种情况下它没有帮助。我需要类似于Queue.put(block=False)或Queue.put_nowait的东西,它会引发队列。完全异常,以便我可以处理管道已满的情况。@Le Quoc Khanh:没有管道已满的情况,您唯一的解决方法是防止
消费者
过程永远流浪。再次感谢您,但根据我的理解,多处理。队列建立在管道之上,它有一些机制来检测和引发队列。队列已满时发生完全异常。我试着阅读多处理库中queues.py的源代码,发现它使用了某种Boundedsemaphore进行检测,但我仍然不理解其逻辑。您对此有什么线索吗?队列
使用大小计数器处理此问题,如果大小计数器等于缓冲区中的数据,则条件FULL为True
。但是为什么要重新发明轮子,为什么Queue
不符合您的需要?因为队列的性能非常慢(比管道慢约3倍),因为队列是通过某种机制实现的,我不需要这种机制(我只在半双工中使用单生产者、单消费者IPC)。因为我必须实时处理大量数据,所以我必须选择使用管道而不是队列。请您更详细地解释一下队列是如何工作的,以检测它是否已满,以及我如何对管道应用类似的方法。我真的很感激。非常感谢你。
Wait till an object in object_list is ready.
Returns the list of those objects in object_list which are ready.
import select
import multiprocessing.connection as mpc
def pipe_full(conn):
r, w, x = select.select([], [conn], [], 0.0)
return 0 == len(w)
i, o = mpc.Pipe(duplex=False)
n = 0
while not pipe_full(o):
o.send(n)
n += 1
print('{} items fit.'.format(n))