简体   繁体   English

在python3中清除异步队列的正确方法?

[英]Proper way to clear an asyncio queue in python3?

Errors in my producer/consumer coroutines may leave items and unfinished tasks in the asyncio queue.我的生产者/消费者协程中的错误可能会在 asyncio 队列中留下项目和未完成的任务。 If an error is encountered, I want to simply stop the loop, cancel the pending tasks and clear the queue.如果遇到错误,我只想停止循环,取消挂起的任务并清除队列。 While I can finish the first two things, I cannot find an easy way to clear the queue.虽然我可以完成前两件事,但我找不到一种简单的方法来清除队列。 After reading this answer , I come up with three methods:看完这个答案后,我想出了三种方法:

import asyncio

q=asyncio.Queue()
for i in range(5):
    q.put_nowait(i)
q.get_nowait()

loop=asyncio.get_event_loop()

#this will raise an error if q cannot join
loop.run_until_complete(asyncio.wait_for(q.join(),1))

#method 1
q._queue.clear()
q._finished.set()
q._unfinished_tasks = 0

#method 2
for _ in range(q.qsize()):
    q.get_nowait()
for _ in range(q._unfinished_tasks):
    q.task_done()

#method 3
del q
q=asyncio.Queue()

So which one is better?那么哪个更好呢?

Avoid using the "private" methods.避免使用“私有”方法。 From the documentation of Queue.task_done :Queue.task_done的文档:

For each get() used to fetch a task, a subsequent call to task_done() tells the queue that the processing on the task is complete.对于用于获取任务的每个 get(),对 task_done() 的后续调用告诉队列该任务的处理已完成。


def empty_queue(q: asyncio.Queue):
  for _ in range(q.qsize()):
    # Depending on your program, you may want to
    # catch QueueEmpty
    q.get_nowait()
    q.task_done()

I did this in various DBussy example scripts :我在各种DBussy 示例脚本中做到了这一点:

for task in asyncio.Task.all_tasks(loop) :
    task.cancel()
    try :
        loop.run_until_complete(task)
    except asyncio.CancelledError :
        pass
    #end try
#end for

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM