When teaching it, it's important to emphasis:
- await is locally blocking, so you should isolate linear workflows into their own coro, which is the unit of concurrency.
- to allow concurrency, you should use asyncio.create_task on coro (formerly ensure_future).
- you should always explicitly delimitate the life cycle of any task. Right now, this means using something like gather() or wait(). TaskGroup will help when it becomes mainstream.
A HN comment is not great to explain that, but if you read the article, you should investigate those points. There is no good asyncio code without them, only pain and disapointment.