Python正在等待队列和事件
我有一个队列和一个事件。我希望在事件设置为True时退出循环,但是循环中有一个queue.get(),它会一直阻塞,直到其中有内容为止 设置closeEvent事件标志时,如何中止self.\u commandQueue.get()的等待 注意:我希望避免依赖于队列的阻塞性质,并希望根据队列的条件和eventflag进行阻塞Python正在等待队列和事件,python,multithreading,python-2.7,multiprocessing,Python,Multithreading,Python 2.7,Multiprocessing,我有一个队列和一个事件。我希望在事件设置为True时退出循环,但是循环中有一个queue.get(),它会一直阻塞,直到其中有内容为止 设置closeEvent事件标志时,如何中止self.\u commandQueue.get()的等待 注意:我希望避免依赖于队列的阻塞性质,并希望根据队列的条件和eventflag进行阻塞 def _execute(self): while not self._closeEvent.isSet(): nextCommand = self
def _execute(self):
while not self._closeEvent.isSet():
nextCommand = self._commandQueue.get()
self._commandExecutor.execute(nextCommand)
self._commandQueue.task_done()
Queue.get
在没有参数的情况下调用时是一种阻塞方法
从文档:
将项目放入队列。如果可选args块为true且超时为
无(默认设置),如有必要,在空闲插槽可用之前阻止。
如果timeout为正数,则它最多会阻止超时秒数和秒数
如果该内存中没有可用的可用插槽,则引发完全异常
时间否则(block为false),如果有空闲项,则将该项放入队列
插槽立即可用,否则引发完全异常(超时
在这种情况下被忽略)
您需要这样做:
try:
# If `False`, the program is not blocked, it will throw the Queue.Empty exception.
my_data = queue.get(False)
.....Some Code......
except Queue.Empty:
my_data = None # or whatever you want
更多选择
get(False)
队列。为空
队列
根据
具体来说,它使用self.not_empty事件,您的应用程序也可以在尝试队列.get_nowait
调用之前等待该事件
至于等待几个事件,有些代码示例存在问题。您可能需要类似Windows
WaitForMultipleObjects()
的调用,但python事件和队列API没有提供这样的beast(但如果您严格使用Windows,则可以使用win32api来使用它),因此,如果您确实需要并行检查两个事件源,那么答案是“如果不进行轮询(或者通过猴子修补事件类来允许轮询),您就不能这样做”
但如果您稍微灵活一点,您可以通过重新定义一点命令队列来安排类似的事情。如果命令队列是PriorityQueue
,则一旦事件发出信号,您可以使用正常优先级对正常作业进行排队,并使用额外的进程队列作为更高优先级的“停止”令牌
STOP = None
def _execute(self):
while 1:
nextCommand = self._commandQueue.get()[1]
if nextCommand is STOP:
break
self._commandExecutor.execute(nextCommand)
self._commandQueue.task_done()
def wait_for_stop_signal(self):
self._closeEvent.wait()
self._commandQueue.put((-1, STOP))
现在,您在自己的线程中运行
wait\u for\u stop\u signal
,您就有了想要的行为(但是浪费一个线程而不是轮询,选择对您的用例更糟糕的方式)。我提供了以下两种选择,它们可能适合:
解决方案1
在你的队列中放一个“神奇的退出标记”。我将不使用,如果需要,您可以使用特殊的退出消息。这与使用优先级队列方法大致相同,但(a)更简单,(b)但队列必须清空到标记点,这可能是您可以接受的,也可能是您不能接受的
例如:
# Untested
# Processing thread
def run(self):
while True:
msg = self.main_queue.get()
if msg == None:
break
...do..queue..work...
def shutdown():
self.main_queue.put(None)
解决方案2
不要打电话给队列,直接走。创建一个事件对象,该对象在以下任一情况下发出信号:
*队列里有东西。
*你想关机吗
定义要添加到队列的方法,而不是将队列公开给外部世界:
def add_to_queue(self, msg):
self.main_queue.put(msg)
self.my_event.set() # Signal the consumer
def shutdown(self, msg):
self.quit_event.set() # Set an event / condvar / msg to indicate exit
self.my_event.set() # Signal something has happened.
def run(self)
while True:
self.my_event.wait()
if self.quit_event.is_set()
break
msg = self.main_queue.get(False) # Empty exception should not happen here
您不一定需要退出事件,因为您可以假设一个空队列和一个有信号的my_事件意味着是时候退出了。尽管如此,我认为最好明确使用适当的指示符—消息、事件、条件变量等。是的,这正是我想要尝试和避免的。我不希望它仅基于队列而阻塞/不阻塞,并永远循环,我希望它阻塞,直到队列不为空且未设置closeEvent标志,然后在
while
条件下使用。这不会解决阻塞问题,它仍然会在while循环中循环。我希望它阻塞,直到队列中有东西并且未设置事件标志。我认为您的建议会使while循环迭代,但不会阻塞。还要注意while循环是一种while-True语句。是的,这就是我想要弄明白的。遗憾地发现python api中没有这样的东西:(您发布的帖子为schlenk所描述的内容提供了另一种选择。非常有用,谢谢:)可能不是等待信号的好风格,这是一个私有api细节,此外,在这种情况下也没有帮助。但是其他线程链接是有用的,尤其是(脏的,猴子补丁)版本,它只是重新定义了事件的作用。。。解决方案1是最佳的!!!