2

I want to run coroutines in __init__, I am using asyncio.create_task to start the execution of the coroutine inside a non-async func (i.e. __init__) to set instance attributes. I need to wait for the first task to finish before returning from __init__. I cannot await the task in __init__, so I tried to use the result of task.done() to check whether it's finished but it did not work, the code got hung and never returned from __init__.

Here's a simple example:

async def coro():
    await asyncio.sleep(2)
    return 2
 
class Foo:
    def __init__(self):
        self._job_id_task = asyncio.create_task(coro()) #Starts running coro()
        while not self._job_1_task.done():
            pass
        self.job_id = self._job_id_task.result()

foo = Foo() #gets hung and never returns Foo object.

Based on my sample code above, I was expecting foo = Foo() to create Foo object in little over 2 seconds, but execution on line foo = Foo() gets hung and never finishes.

1
  • 1
    Do you have an event loop running? Commented Jun 18, 2021 at 23:33

2 Answers 2

2

Your program is getting stuck because you are not running the event loop. You can run the event loop in another thread like this:

import asyncio
from threading import Thread

async def coro():
    await asyncio.sleep(2)
    return 2

def run_loop_in_thread(loop):
    asyncio.set_event_loop(loop)
    loop.run_forever()

loop = asyncio.get_event_loop()
coro_thread = Thread(target=run_loop_in_thread, args=(loop,))
coro_thread.start()

class Foo:
    def __init__(self):
        future = asyncio.run_coroutine_threadsafe(coro(), loop)
        self.job_id = future.result()

foo = Foo()
Sign up to request clarification or add additional context in comments.

Comments

0

The simpler way would be to use run_until_complete

Your code would be like this:

import asyncio
async def coro():
    await asyncio.sleep(2)
    return 2
 
class Foo:
    def __init__(self):

        loop = asyncio.get_event_loop()
        result =loop.run_until_complete(coro())    
        self.job_id = result

        print(self.job_id)


foo = Foo() #gets hung and never returns Foo object.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.