John
John

Reputation: 47

Python asyncio wait and notify

I am trying to do something similar like C# ManualResetEvent but in Python.

I have attempted to do it in python but doesn't seem to work.

import asyncio

cond = asyncio.Condition()

async def main():
    some_method()

    cond.notify()

async def some_method():
    print("Starting...")
    
    await cond.acquire()
    await cond.wait()
    cond.release()
    
    print("Finshed...")

main()

I want the some_method to start then wait until signaled to start again.

Upvotes: 0

Views: 1386

Answers (2)

Eric Chow
Eric Chow

Reputation: 479

For Python 3.10

To make sure the lock is release no matter what. We can use try--finally.

like

await cond.acquire()
try:
    await cond.wait()
finally:
    cond.release()

And we already have a convenient way (context manager) to do that:

async with cond:
    await cond.wait()

notify() and notify_all() also need the lock.

async with cond:
    cond.notify_all()

Upvotes: 0

Bluenix
Bluenix

Reputation: 429

This code is not complete, first of all you need to use asyncio.run() to bootstrap the event loop - this is why your code is not running at all.

Secondly, some_method() never actually starts. You need to asynchronously start some_method() using asyncio.create_task(). When you call an "async def function" (the more correct term is coroutinefunction) it returns a coroutine object, this object needs to be driven by the event loop either by you awaiting it or using the before-mentioned function.

Your code should look more like this:

import asyncio

async def main():
    cond = asyncio.Condition()

    t = asyncio.create_task(some_method(cond))

    # The event loop hasn't had any time to start the task
    # until you await again. Sleeping for 0 seconds will let
    # the event loop start the task before continuing.
    await asyncio.sleep(0)
    cond.notify()

    # You should never really "fire and forget" tasks,
    # the same way you never do with threading. Wait for
    # it to complete before returning:
    await t

async def some_method(cond):
    print("Starting...")
    
    await cond.acquire()
    await cond.wait()
    cond.release()
    
    print("Finshed...")

asyncio.run(main())

Upvotes: 1

Related Questions