python-dependency-injector icon indicating copy to clipboard operation
python-dependency-injector copied to clipboard

create task for a coroutine that depends on an async factory

Open pikrog opened this issue 2 years ago • 0 comments
trafficstars

I have a dependency injection container that holds a coroutine. This coroutine takes some object as a parameter. Also that object is managed by the container - it is created via a factory method but the method itself is asynchronous. The code snippet below depicts clearly how it is done:

import asyncio

from dependency_injector import containers, providers


async def create_a():
    await asyncio.sleep(1)
    return 1


async def run(a: int):
    await asyncio.sleep(1)
    return a


class Container(containers.DeclarativeContainer):
    a = providers.Factory(
        create_a
    )

    run_a = providers.Coroutine(
        run,
        a=a,
    )


async def main():
    container = Container()
    asyncio.create_task(container.run_a())


if __name__ == "__main__":
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(main())

If create_a was a normal synchronous function, then the code above would run as expected. However, with an async create_a an exception is raised while trying to create a task for container.run():

Traceback (most recent call last):
  File "C:\Users\-\Desktop\coro\main.py", line 35, in <module>
    loop.run_until_complete(main())
  File "C:\Python310\lib\asyncio\base_events.py", line 641, in run_until_complete
    return future.result()
  File "C:\Users\-\Desktop\coro\main.py", line 29, in main
    asyncio.create_task(container.run())
  File "C:\Python310\lib\asyncio\tasks.py", line 337, in create_task
    task = loop.create_task(coro)
  File "C:\Python310\lib\asyncio\base_events.py", line 433, in create_task
    task = tasks.Task(coro, loop=self, name=name)
TypeError: a coroutine was expected, got <Future pending>

At first glance, I thought that I need to await container.run() to acquire the actual coroutine object and then pass it to asyncio.create_task() but this way await just runs the run coroutine and blocks execution which is not what I want. What am I doing wrong?

pikrog avatar Dec 31 '22 15:12 pikrog