Beckicious
Beckicious

Reputation: 58

python asyncio: Wait in coroutine for intermediate result of another coroutine

I have 2 coroutines (co_A, co_B) in different classes (class_A, class_B) that are called regularly by a scheduler. At some time during the execution co_B needs a result that co_A is calculating during its run.

What I would like to do is something like this:

class class_A:
    async def co_A(self):

        # execute time consuming code

        # set result that co_B needs
        self.set_result(result)

        # execute more time consuming code

class class_B:
    async def co_B(self):

        # execute time consuming code

        # wait for result from co_A
        result = await class_A_instance.get_result()

        # execute more time consuming code

My approach is to have an empty Future in class_A that gets filled during co_A and in co_B wait in a loop until the Future is set:

class class_A:
    async def prepare(self):
        self.fut = asyncio.Future()

    async def co_A(self):

        # execute time consuming code

        # set result that co_B needs
        self.fut.set_result(result)

        # execute more time consuming code

class class_B:   
    async def co_B(self):

        # execute time consuming code

        # wait for result from co_A
        while not class_A_instance.fut.done():
            await asyncio.sleep(0)

        result = class_A_instance.fut.result()

        # execute more time consuming code

Is there a better way to do this without having to sleep in a loop until co_A has calculated the result?

Upvotes: 4

Views: 1031

Answers (2)

kwarunek
kwarunek

Reputation: 12597

I would use Event class to synchronize coroutines. @Mikhail approach is 100% correct but doesn't address that you would like to get notified in the middle of co_A.

class A:
    def __init__(self):
        self.partially_ready = asyncio.Event()

    async def prepare(self):
        self.partially_ready.clear()

    async def co_A(self):   
        # execute time consuming code

        # set result that co_B needs
        self.partially_ready.set()
        # execute more time consuming code


class class_B:   
    async def co_B(self):

        # execute time consuming code

        # wait for result from co_A
        await A_instance.partially_ready.wait()
        # here A_instance finished some part you would like to wait

Upvotes: 1

Mikhail Gerasimov
Mikhail Gerasimov

Reputation: 39606

Whole idea of futures is that you can await for it just like for coroutines, tasks, etc.

class class_B:   
    async def co_B(self):

        # execute time consuming code

        # wait for result from co_A
        result = await class_A_instance.fut

        # execute more time consuming code

See section "Things a coroutine can do" here.

Upvotes: 1

Related Questions