【问题标题】:asyncio Queue.get delayasyncio Queue.get 延迟
【发布时间】:2019-05-09 04:50:20
【问题描述】:

我有以下代码:

import asyncio
import threading
import time

q = asyncio.Queue()

async def ping():
    while True:
        await asyncio.sleep(10)
        print("ping")

async def rcv():
    while True:
        item = await q.get()
        print("got item")

async def run():
    tasks = [asyncio.ensure_future(ping()), asyncio.ensure_future(rcv())]
    await asyncio.wait(tasks, return_when="FIRST_EXCEPTION")

loop = asyncio.get_event_loop()

def run_loop():
    asyncio.set_event_loop(loop)
    loop.run_until_complete(run())

threading.Thread(target=run_loop).start()

while True:
    time.sleep(2)
    q.put_nowait("item")
    print("item added")

我预计每 2 秒(每次将项目添加到队列中),我会看到输出:

item added
sleeping 2 seconds
got item

每隔 10 秒我还会看到 ping

但是,这是我得到的输出(重复):

sleeping 2 seconds
item added
sleeping 2 seconds
item added
sleeping 2 seconds
item added
sleeping 2 seconds
item added
sleeping 2 seconds
got item
got item
got item
got item
ping
item added
sleeping 2 seconds
...

似乎item = await q.get() 部分也在等待来自ping 函数的asyncio.sleep(10)

我错过了什么?以及如何修复代码以获得预期的输出?

谢谢!

【问题讨论】:

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


    【解决方案1】:

    我错过了什么?以及如何修复代码以便获得预期的输出?

    由于您在单独的线程中运行事件循环,您需要将q.put_nowait("item") 更改为:

    loop.call_soon_threadsafe(q.put_nowait, "item")
    

    原因是 asyncio 代码(有意)不是线程安全的,因此使用 put_nowait 不会通知事件循环新项目已入队。

    【讨论】:

    • 你是否也可以使用 put(),不使用 nowait,以类似的方式避免完整队列异常
    • @cIph3r OP 的队列是无限的,所以问题从未出现。你不能将q.put 传递给call_soon_threadsafe 接受同步函数,而Queue.put 是异步的。但您可以使用asyncio.run_coroutine_threadsafe 代替:asyncio.run_coroutine_threadsafe(q.put("item"), loop).result()run_coroutine_threadsafe 返回一个 concurrent.futures.Future(不要与 asyncio Future 混淆),其 result() 方法等待底层协程完成,即在这种情况下 put 实际在队列中找到一个空闲槽。跨度>
    • 请注意,等待结果失败将破坏有界队列的目的,因为它会导致任务在事件循环中无限制地累积,并且无法提供预期的背压。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-28
    • 2020-11-02
    • 2019-02-20
    • 1970-01-01
    • 2022-11-29
    • 2017-07-28
    相关资源
    最近更新 更多