Daniel Pope wrote a great blog post describing the different ways of performing asynchronous I/O in Python. In this post, I want to focus on his section called “Generator-based Coroutine”. Python’s
asyncio module in the standard library has a concept of “coroutines” that uses generators instead of callbacks or promises seen in other asynchronous frameworks.
Whenever a I/O call is made, you can prepend the statement with
yield from and as long as the function is under the
asyncio.coroutine generator, the Python module will handle the call asynchronously. Now this method doesn’t fully fit under the coroutine framework since generators can only yield to the caller frame. Therefore, it is called a semicoroutine.
Here is an example of its usage
import asyncio @asyncio.coroutine def think(duration): print("Starting to think for " + str(duration) + " seconds...") yield from asyncio.sleep(duration) print("Finished thinking for " + str(duration) + " seconds...") loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.gather( think(5), think(2) )) loop.close()
Starting to think for 5 seconds... Starting to think for 2 seconds... Finished thinking for 2 seconds... Finished thinking for 5 seconds...
Now the decorator syntax has been deprecated in Python 3.8 in favor of the more common
await syntax introduced in Python 3.7. The reason I showed the previous version is because I think it’s important to understand how this module is implemented behind the scenes. Also since Python 3.6 code is likely still floating around, you might encounter code bases like the above in your day to day.
Here is the equivalent code written in modern day syntax
import asyncio async def think(duration): print("Starting to think for " + str(duration) + " seconds...") await asyncio.sleep(duration) print("Finished thinking for " + str(duration) + " seconds...") async def main(): await asyncio.gather( think(2), think(5) ) asyncio.run(main())
Not that much shorter in terms of lines of code, but it allows the developer to not have to be concerned about the event loop or generators.