Last time, we saw you can leverage ThreadPool for multiprocessing:
You may also appreciate a convenient
async/await syntax to execute tasks asynchronously, and that's exactly what
Asyncio allows writing concurrent code.
You will often see it in professional usages.
However, you might not know that Asynchronous IO uses a single thread in a single process.
It's a bit counterintuitive, and you may find many usages for "concurrent code," but tasks are not inherently concurrent.
It's another approach that is different from threading or multiprocessing, by design.
The bad practice would be to use
await for anything and everything.
To me, you should focus more on the asynchronous vs. synchronous code than "concurrency."
async with, you will manipulate coroutines and use the
await to suspend their execution until you get something you are waiting for.
That's pretty much what "coroutine" means: a function that can pause its execution for other operations.
To define a coroutine, just use
import asyncio async def test(): print("test") if __name__ == '__main__': asyncio.run(test())
To pause the execution, use
import asyncio async def test(): await asyncio.sleep(7) return "test" async def main(): t = await test() print(t) if __name__ == '__main__': asyncio.run(main())
You can see
await as break points.
In my experience, the benefits of Async IO can be multiple:
- non-blocking calls, especially with HTTP requests
- optimized CPU usage
- awaitable objects
- ability to chain coroutines
However, there are some cons:
- can be harder to debug
- it's easy to misuse it (e.g., using async along with blocking calls)