4 ms·
It gives good pointers but it falls short on the usual suspects for an article on asyncio. When teaching it, it's important to emphasis: - await is locally bl
by BiteCode_dev 4y ago
It gives good pointers but it falls short on the usual suspects for an article on asyncio.
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.
- uniqueuid 4y ago> you should always explicitly delimitate the life cycle of any task Unless you want a hacky actor system, in which case it's totally fine to `create_task` a ton of corountines which have their own spin loop with await sleep :)
- lozenge 4y agoOne coroutine crashing and the others continuing to send it messages without noticing was my $40,000 bug.
- Spivak 4y agoI’m so confused by this architecture. It makes total sense in a threaded world but why would you want a coroutine constantly scheduling itself in a loop to pull messages off a queue like thing than just having the thing generating the message fire off a task to process it directly right there? It feels almost the same to me and then you can’t crash the coroutine.
- BiteCode_dev 4y agoAt some point even those tasks must be cleanly stopped and unless you want to play erlang and "let it crash", the actors have a lifecycle as well. Making it explicit will avoid much pain, and ease testing a lot. Also it will make resources consumption more predictable.
- aserafini 4y agoEven if you want to ‘fire and forget’, it’s still essential to keep a reference to the task, otherwise it can be garbage collected mid-execution: https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task https://docs.python.org/3/library/asyncio-task.html#asyncio....
- rolobio 4y agoWow! Did not know this, guess I’ve got a couple fixes to make…
- quietbritishjim 4y ago> ... TaskGroup will help when it becomes mainstream. Strongly agreed, but you can use anyio [1] in to of asyncio to get that functionality right now. Or, maybe even better, use Trio [2] instead, which is where the idea came from in the first place. [1] https://anyio.readthedocs.io/en/stable/ https://anyio.readthedocs.io/en/stable/ [2] https://trio.readthedocs.io/en/stable/ https://trio.readthedocs.io/en/stable/
- throwway2332 4y ago> to allow concurrency, you should use asyncio.create_task on coro (formerly ensure_future). This is misleading... you can use asyncio.gather which does this internally [0]. [0]: https://github.com/python/cpython/blob/main/Lib/asyncio/tasks.py#L820 https://github.com/python/cpython/blob/main/Lib/asyncio/task...
- BiteCode_dev 4y agoOnly if you wish to collect tasks where you schedule them, accumulate the results and don't need to limit concurrency.
- Spivak 4y agoSerious question, why would you limit concurrency in async world? You’re still on a single thread, why would you want to only schedule n things at a time?