我觉得这应该是一个简单的解决方案,但今天结束了,我脑死亡。我目前正在生成几个进程,一个进程正在接收和存储数据到文件。另一个是解析数据,第三个是等待用户输入,以知道何时停止数据存储。
我需要知道的是如何中断我的while循环。我不想使用父进程设置的全局变量,但如果需要,我可以这样做。现在我的代码看起来像这样:
while(packetReceived < totalToReceive):
data, addr = sock.recvfrom(packetSize)
我的想法是这样的:
breakout = 0
while(packetReceived < totalToReceive || breakout != 0):
data, addr = sock.recvfrom(packetSize)
但是我需要设置breakout。
不能仅仅通过在父进程中使用全局变量来共享状态。这可能看起来有效,但它只是有时有效;它既不可靠,也不可预测。除了在Windows上,它可靠而可预测地永远不会工作;每个子节点都有自己独立的flag副本,因此你永远不会退出。
如果您真的想通过共享变量来实现这一点,请参阅文档中进程之间的共享状态,但简短的版本是:您创建一个multiprocessing.Value
。然后您使用multiprocessing.Condition
来保护该值不受竞争的影响,因为否则,就不能保证子进程会看到来自父进程的更改。
当然,您可以通过创建最小大小的mmap
并仅使用m[0]
作为标志和m.flush()
而不是条件来实现这一点,但这并不真正简单。
另一种方法是使用multiprocessing.Pipe
或类似的方式传递"立即关闭"消息。子进程可以每个生成一个线程来阻塞管道,或者您可以将管道和套接字一起扔到select
中,或者使用所有其他常用的技巧。
multiprocessing
。显然,您的后台任务不是cpu限制的,因为它只是循环从套接字读取,所以为什么不只是threading
呢?
而且,我突然想到,您也许可以用其他方法简化您的设计,从而完全消除这个问题。在读取和处理作业之间是否需要一个文件,而不是一个队列,或者甚至只是一个直接的顺序管道?你是否可以将用户输入和套接字放入同一个事件循环(如果用户输入是stdin
,则普通的select
,并且你不关心Windows;如果用户输入是Qt GUI,使用QSocket
而不是socket.socket
;twisted
,如果你愿意学习twisted
;等等)。或者,是否存在真正的用户输入,或者只是"立即退出"(或"立即关闭套接字并处理剩余的消息"),您可以使用^C处理这些输入?
考虑检查是否存在"毒丸"以跳出循环,而不是使用多处理变量。
例如:
data, addr = sock.recvfrom(packetSize)
转换成:
received = sock.recvfrom(packetSize)
if received is None:
break
data, addr = received
可以通过发送None
值来通知进程跳出循环。我不确定你的sock
是否可以发送/接收None
,但一般的想法是一样的。