从线程队列获取所有项目

Eli*_*sky 14 python queue multithreading

我有一个线程将结果写入队列.

在另一个线程(GUI)中,我定期(在IDLE事件中)检查队列中是否有结果,如下所示:

def queue_get_all(q):
    items = []
    while 1:
        try:
            items.append(q.get_nowait())
        except Empty, e:
            break
    return items
Run Code Online (Sandbox Code Playgroud)

这是一个很好的方法吗?

编辑:

我问,因为有时等待的线程会卡住几秒而不会取出新的结果.

"卡住"问题原来是因为我在空闲事件处理程序中进行处理,而不是确保通过调用实际生成这样的事件wx.WakeUpIdle,如建议的那样.

Bri*_*ian 16

如果你总是从队列中提取所有可用的项目,那么使用队列是否有任何实际意义,而不仅仅是一个带锁的列表?即:

from __future__ import with_statement
import threading

class ItemStore(object):
    def __init__(self):
        self.lock = threading.Lock()
        self.items = []

    def add(self, item):
        with self.lock:
            self.items.append(item)

    def getAll(self):
        with self.lock:
            items, self.items = self.items, []
        return items
Run Code Online (Sandbox Code Playgroud)

如果您还单独提取它们并利用空队列的阻塞行为,那么您应该使用Queue,但您的用例看起来更简单,并且可能更好地通过上述方法提供服务.

[Edit2] 我错过了你从空闲循环中轮询队列的事实,从你的更新中,我发现问题与争用无关,所以下面的方法与你的问题没有关系.我把它留在了以防万一有人发现这个有用的阻塞变种:

对于您确实要阻止直到获得至少一个结果的情况,您可以修改上述代码以等待数据通过生产者线程发出信号而变得可用.例如.

class ItemStore(object):
    def __init__(self):
        self.cond = threading.Condition()
        self.items = []

    def add(self, item):
        with self.cond:
            self.items.append(item)
            self.cond.notify() # Wake 1 thread waiting on cond (if any)

    def getAll(self, blocking=False):
        with self.cond:
            # If blocking is true, always return at least 1 item
            while blocking and len(self.items) == 0:
                self.cond.wait()
            items, self.items = self.items, []
        return items
Run Code Online (Sandbox Code Playgroud)


Gab*_*Gab 10

我认为将所有项目排除在队列之外的最简单方法如下:

def get_all_queue_result(queue):

    result_list = []
    while not queue.empty():
        result_list.append(queue.get())

    return result_list
Run Code Online (Sandbox Code Playgroud)

  • 这在某些时候仍然可能会给你一个例外。来自文档:如果 empty() 返回 True 它不能保证对 put() 的后续调用不会阻塞。类似地,如果 empty() 返回 False 它不能保证对 get() 的后续调用不会阻塞。https://docs.python.org/2/library/queue.html (2认同)

Jon*_*age 9

如果get_nowait()呼叫导致暂停,如果列表为空则不返回,我会感到非常惊讶.

可能是你在检查之间发布了大量(可能是大的?)项目,这意味着接收线程有大量数据要从中拉出来Queue?您可以尝试限制一批中检索的数字:

def queue_get_all(q):
    items = []
    maxItemsToRetreive = 10
    for numOfItemsRetrieved in range(0, maxItemsToRetreive):
        try:
            if numOfItemsRetrieved == maxItemsToRetreive:
                break
            items.append(q.get_nowait())
        except Empty, e:
            break
    return items
Run Code Online (Sandbox Code Playgroud)

这会限制接收线程一次最多提取10个项目.


Eve*_*rtW 5

最简单的方法是使用列表理解:

items = [q.get() for _ in range(q.qsize())]
Run Code Online (Sandbox Code Playgroud)

使用该range函数通常不受欢迎,但我还没有找到更简单的方法。