程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

2022年1月3日 Python asyncio.Queue的get()和task_done()

編輯:Python

對於asyncio的隊列,使用get()時就已經把隊列中的元素彈出了,而task_done()只是減少未完成任務數量。
這是我找到的相關資料(雖然是線程的隊列,但協程的應該也同理):
https://stackoverflow.com/questions/1593299/python-queue-get-task-done-issue/1593330#1593330

No, queue.get() pops the item off the queue. After you do that, you can do whatever you want with it, as long as the producer works like it should and doesn’t touch it anymore. queue.task_done() is called only to notify the queue that you are done with something (it doesn’t even know about the specific item, it just counts unfinished items in the queue), so that queue.join() knows the work is finished.

之後,我實踐了一下。

>>> import asyncio
>>> queue=asyncio.Queue(5)
>>> async def sb():
while 1:
await queue.put(1)
print(queue)
>>> async def cnm():
while 1:
await queue.get()
print(queue)
queue.task_done()
print(queue)
>>> async def main():
task=asyncio.create_task(sb())
await asyncio.sleep(5)
task.cancel()
asyncio.create_task(cnm())
>>> asyncio.run(main())
<Queue maxsize=5 _queue=[1] tasks=1>
<Queue maxsize=5 _queue=[1, 1] tasks=2>
<Queue maxsize=5 _queue=[1, 1, 1] tasks=3>
<Queue maxsize=5 _queue=[1, 1, 1, 1] tasks=4>
<Queue maxsize=5 _queue=[1, 1, 1, 1, 1] tasks=5>
<Queue maxsize=5 _queue=[1, 1, 1, 1] tasks=5>
<Queue maxsize=5 _queue=[1, 1, 1, 1] tasks=4>
<Queue maxsize=5 _queue=[1, 1, 1] tasks=4>
<Queue maxsize=5 _queue=[1, 1, 1] tasks=3>
<Queue maxsize=5 _queue=[1, 1] tasks=3>
<Queue maxsize=5 _queue=[1, 1] tasks=2>
<Queue maxsize=5 _queue=[1] tasks=2>
<Queue maxsize=5 _queue=[1] tasks=1>
<Queue maxsize=5 tasks=1>
<Queue maxsize=5>

可以看到,使用get()後,隊列中的元素減少了,但是tasks沒有減少,使用task_done()後tasks才減少。
查看queue的屬性:

猜測_unfinished_tasks是上面的tasks。
驗證:

>>> async def cnm():
while 1:
await queue.get()
print(queue._unfinished_tasks)
queue.task_done()
print(queue._unfinished_tasks)
>>> asyncio.run(main())
<Queue maxsize=5 _queue=[1] tasks=1>
<Queue maxsize=5 _queue=[1, 1] tasks=2>
<Queue maxsize=5 _queue=[1, 1, 1] tasks=3>
<Queue maxsize=5 _queue=[1, 1, 1, 1] tasks=4>
<Queue maxsize=5 _queue=[1, 1, 1, 1, 1] tasks=5>
5
4
4
3
3
2
2
1
1
0

猜測正確。
因此,如果不從隊列中取出值而直接用task_done()的話會使隊列中還有元素,但是未完成的任務數量為0。

>>> queue.put_nowait(2)
>>> queue
<Queue at 0x24cf9965610 maxsize=5 _queue=[2] tasks=1>
>>> queue.task_done()
>>> queue
<Queue at 0x24cf9965610 maxsize=5 _queue=[2]>

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved