如何将项目推出asyncio.PriorityQueue当它在maxsize和我put()新项目?

2024-04-20 13:21:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个asyncio.PriorityQueue作为web爬虫程序的URL队列,得分最低的URL是我调用url_queue.get()时从队列中第一个删除的URL。当队列到达maxsize个项目时,默认行为是阻止对url_queue.put()的调用,直到对get()的调用从队列中删除一个项目以腾出空间。在

我想做的是永远不要阻塞,而是在我试图put()一个得分较低的项目时,推掉得分最高的队列项目(或者至少是得分最高的项目)。在asyncio.PriorityQueue中,有没有一种方法可以自动从堆底部删除项?如果没有,是否有其他优先级队列/堆实现可以与asyncio一起工作,这将使我能够做到这一点?或者其他一些数据结构/技术,使我能够拥有某种非阻塞的、优先级最高的队列?在

谢谢!在


Tags: 项目方法程序webasynciourlget队列
1条回答
网友
1楼 · 发布于 2024-04-20 13:21:30

Is there a way to automatically remove items from the bottom of the heap this way in asyncio.PriorityQueue?

默认情况下不是这样,但是从asyncio.PriorityQueue继承并实现所需的行为应该很简单。与多线程队列实现不同,asyncio队列在单个线程中运行,因此不需要担心同步问题。在

性能方面可能存在的一个问题是,PriorityQueue不是设计为双端队列的,因此它使用堆来存储项。堆可以是minmax,但不是两者都是;Python的heapq模块实现了一个最小堆,但是可以通过将优先级乘以-1来轻松模拟max堆。在最小堆中,可以在对数时间内访问和弹出最小的项,但不能访问最大的项,而在最大堆中则相反。为了有效地操作最小和最大的项,需要从asyncio.Queue继承并使用不同的数据结构来存储项,例如sorted list。在

例如(未测试):

class DroppingPriorityQueue(asyncio.Queue):
    def _init(self, maxsize):
        # called by asyncio.Queue.__init__
        self._queue = sortedcontainers.SortedList()

    def _put(self, item):
        # called by asyncio.Queue.put_nowait
        self._queue.add(item)

    def _get(self):
        # called by asyncio.Queue.get_nowait
        # pop the first (most important) item off the queue
        return self._queue.pop(0)

    def __drop(self):
        # drop the last (least important) item from the queue
        self._queue.pop()
        # no consumer will get a chance to process this item, so
        # we must decrement the unfinished count ourselves
        self.task_done()

    def put_nowait(self, item):
        if self.full():
            self.__drop()
        super().put_nowait(item)

    async def put(self, item):
        # Queue.put blocks when full, so we must override it.
        # Since our put_nowait never raises QueueFull, we can just
        # call it directly
        self.put_nowait(item)

该类实现了两个不同的关注点:

  • 它重写_get_put和{}受保护的方法,以使用^{}作为底层存储。尽管这些方法没有文档化,但它们用于构建定制队列,如^{}和{a4},并且已经存在了几十年,首先是在Queue模块中(queue在Python3中)和随后的asyncio.queue。在
  • 它重写putput_nowait公共方法来实现drop when full语义。在

相关问题 更多 >