Skip to content

asyncio.Queue won't wake up when put is executed in separate thread #97970

Description

@sergey-p3

Bug report

When await queue.put() is called from another thread it never awakens original thread waiting for the value i.e. await queue.get()

Minimal, Reproducible Example

import asyncio
import threading


async def delayed_execution(queue, some_value):
    await asyncio.sleep(0.1)
    print("Delayed execution triggered")
    await queue.put(some_value)
    print("Delayed execution finished")


async def main():
    queue = asyncio.Queue()
    thread = threading.Thread(target=asyncio.run, args=(delayed_execution(queue, 1),))
    thread.start()
    print("Delayed execution 1 result:", await queue.get()) # never printed


if __name__ == "__main__":
    asyncio.run(main())

Your environment

  • Python 3.10.7, Ubuntu 20.04.5 LTS
  • Docker amd64/python:3.9-slim-buster

When the code is launched with ensure_future instead of a thread, it works as expected. (see main2)

When the code is launched without with a while loop checking for the queue not to be empty, the value is available. (see main3)

The same code as above, with the two extra tests

import asyncio
import threading


async def delayed_execution(queue, some_value):
    await asyncio.sleep(0.1)
    print("Delayed execution triggered")
    await queue.put(some_value)
    print("Delayed execution finished")


async def main():
    queue = asyncio.Queue()

    thread = threading.Thread(target=asyncio.run, args=(delayed_execution(queue, 1),))
    thread.start()

    print("Delayed execution 1 result:", await queue.get()) # never printed


async def main2():
    queue = asyncio.Queue()

    asyncio.ensure_future(delayed_execution(queue, 2))

    print("Delayed execution 2 result:", await queue.get()) # printed


async def main3():
    queue = asyncio.Queue()

    thread = threading.Thread(target=asyncio.run, args=(delayed_execution(queue, 3),))
    thread.start()

    while queue.empty():
        await asyncio.sleep(0.1)
    print("Delayed execution 3 result:", await queue.get()) # printed


if __name__ == "__main__":
    asyncio.run(main2())
    asyncio.run(main3())
    asyncio.run(main())

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions