【问题标题】:Joinable PriorityQueue in python's asynciopython的asyncio中的可加入PriorityQueue
【发布时间】:2015-09-30 23:16:23
【问题描述】:

根据documentation,队列有几种实现。我感兴趣的是 JoinableQueue 和 PriorityQueue,因为我想要一个具有优先级的可连接队列。

看来我只能获得较低版本中的一项功能。 IE。在 3.5 中,我可以使用 Queue(可连接)和 PriorityQueue 进行区分,但在 3.5 以下的 python 中,有 JoinableQueue 和 PriorityQueue(参见下面的示例)。

是否有可能将它们结合起来以获得在 3.4 中获得可连接 PriorityQueue 的通用方法?

try:
    # Python 3.4.
    from asyncio import JoinableQueue as Queue # joinable
    from asyncio import PriorityQueue          # I assume this one is not joinable
except ImportError:
    # Python 3.5.
    from asyncio import Queue                  # standard joinable
    from asyncio import PriorityQueue          # I assume this is the one I want

另一种方法可能是以某种方式影响队列?

【问题讨论】:

    标签: python python-3.x asynchronous queue python-asyncio


    【解决方案1】:

    由于JoinableQueuePriorityQueue的实现方式,只要先列出JoinableQueue,就可以通过多重继承继承JoinablePriorityQueue

    之所以可行,是因为PriorityQueue 的实现非常简单:

    class PriorityQueue(Queue):
        """A subclass of Queue; retrieves entries in priority order (lowest first).
    
        Entries are typically tuples of the form: (priority number, data).
        """
    
        def _init(self, maxsize):
            self._queue = []
    
        def _put(self, item, heappush=heapq.heappush):
            heappush(self._queue, item)
    
        def _get(self, heappop=heapq.heappop):
            return heappop(self._queue)
    

    虽然JoinableQueue 更复杂,但它和PriorityQueue 实现的唯一方法是_put,而且至关重要的是,JoinableQUeue 在自己的super()._put(..) 实现中调用super()._put(..),这意味着它将与PriorityQueue 正确。

    这是一个证明它有效的例子:

    from asyncio import PriorityQueue, JoinableQueue
    import asyncio
    import random
    
    class JoinablePriorityQueue(JoinableQueue, PriorityQueue):
        pass
    
    
    @asyncio.coroutine
    def consume(q):
        while True:
            a = yield from q.get()
            print("got a {}".format(a))
            if a[1] is None:
                q.task_done()
                return
            asyncio.sleep(1)
            q.task_done()
    
    @asyncio.coroutine
    def produce(q):
        for i in range(10):
            yield from q.put((random.randint(0,10), i))
        yield from q.put((100, None)) # Will be last
        asyncio.async(consume(q))
        print("waiting...")
        yield from q.join()
        print("waited")
    
    loop = asyncio.get_event_loop()
    q = JoinablePriorityQueue()
    loop.run_until_complete(produce(q))
    

    输出:

    waiting...
    got a (1, 2)
    got a (2, 1)
    got a (4, 4)
    got a (5, 0)
    got a (6, 8)
    got a (6, 9)
    got a (8, 3)
    got a (9, 5)
    got a (9, 7)
    got a (10, 6)
    got a (100, None)
    waited
    

    【讨论】:

    • 我希望通过一种方式来引起你的注意,因为我知道你参与了 aio :)
    • @PascalvKooten 我没有开发任何核心asyncio 代码,只是构建在它之上的第三方模块(aioprocessing)。我已经在 SO 上回答了很多关于它的问题。 Andrew Svetlov,在这里也回答了很多关于 asyncio 的问题,我相信确实开发了一些核心代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-28
    相关资源
    最近更新 更多