Python 除了asyncio.Queue.put中的错误之外,其他错误?

Python 除了asyncio.Queue.put中的错误之外,其他错误?,python,python-3.5,python-asyncio,Python,Python 3.5,Python Asyncio,asyncio\queues.py @coroutine def put(self, item): """Put an item into the queue. Put an item into the queue. If the queue is full, wait until a free slot is available before adding item. This method is a coroutine. """ while

asyncio\queues.py

@coroutine
def put(self, item):
    """Put an item into the queue.

    Put an item into the queue. If the queue is full, wait until a free
    slot is available before adding item.

    This method is a coroutine.
    """
    while self.full():
        putter = futures.Future(loop=self._loop)
        self._putters.append(putter)
        try:
            yield from putter
        except:
            putter.cancel()  # Just in case putter is not done yet.
            if not self.full() and not putter.cancelled():
                # We were woken up by get_nowait(), but can't take
                # the call.  Wake up the next in line.
                self._wakeup_next(self._putters)
            raise
    return self.put_nowait(item)
在我看来,推杆可以通过取消、设置例外或设置结果来完成。获取\u nowait使用设置\u结果。只有cancel和set_异常才会引发异常,然后exception:才能发生。我认为除了:不需要

为什么它添加了一个例外:唤醒下一个队列

更新:@Vincent
_唤醒\u下一次呼叫设置\u结果。设置结果将执行self.\u state=\u FINISHED。task1.cancel将自动取消。fut\u服务员。cancel返回False。因此,task1不会被取消

@文森特,非常感谢

主要原因是任务。取消可以取消任务,尽管任务正在等待的未来已经设置。\u resultself.\u state=\u FINISHED.

如果等待推杆的任务被取消,推杆的屈服将引发取消错误。这可能发生在调用get_nowait之后,并且您希望确保通知其他推杆,队列中有一个新插槽可用

下面是一个例子:

async def main():
    # Create a full queue
    queue = asyncio.Queue(1)
    await queue.put('A')
    # Schedule two putters as tasks
    task1 = asyncio.ensure_future(queue.put('B'))
    task2 = asyncio.ensure_future(queue.put('C'))
    await asyncio.sleep(0)
    # Make room in the queue, print 'A'
    print(queue.get_nowait())
    # Cancel task 1 before giving the control back to the event loop
    task1.cancel()
    # Thankfully, the putter in task 2 has been notified
    await task2
    # Print 'C'
    print(await queue.get())
编辑:有关内部情况的更多信息:

queue.get\u nowait:putter.set\u resultNone被调用;推杆状态现在已完成,当控件返回到事件循环时,task1将唤醒。 task1.cancel:task1.\u fut\u water已完成,因此task1.\u must\u cancel设置为True,以便在下次运行task1时引发CanceledError。 等待任务2: 控制返回到控制循环,task1.\u步骤运行。在协同程序中抛出一个取消错误:task1.\u coro.throwCancelledError。 queue.put捕获异常。由于队列未满且不会插入“B”,因此必须通知队列中的下一个推杆:self.\u wakeup\u nextself.\u推杆。 然后,将重新引发取消错误并在task1中捕获。\u步骤。task1现在实际上会自动取消super.cancel。
_唤醒\u下一次呼叫设置\u结果。设置结果将执行“self.\u state=\u FINISHED”。task1.cancel将“self.\u fut\u water.cancel”,返回False。@文斯task1和推杆不是同一个未来。推杆task1.\u fut\u water确实已完成,但task1尚未完成,直到它被取消且task1.\u must\u cancel设置为True。在这种情况下,task1.cancel时task1未启动,因此它只是在启动前被取消。get_nowait不会唤醒未触发task1中的任何putterexcept。也许我们需要创建一个示例来取消正在运行的task1。@Vince,看看我的编辑是否有帮助。你也可以用self运行我的示例。_wakeup_nextself。_putters注释掉了。您应该注意到,程序挂起是因为队列.put'C'尚未收到通知。它在注释后不会挂起