Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Agree, asyncio is a mess; Trio gets it right.

https://trio.readthedocs.io/

It's a much simpler model that's just as powerful, and makes it easy to get things right. It eliminates the concepts of futures, promises, and awaitables. It has only one way to wait for a task: await it.

For a theoretical explanation of it's "structured concurrency" model see the now-famous essay https://vorpus.org/blog/notes-on-structured-concurrency-or-g...



Nathaniel has done a great job of drawing parallels between go and goto.

I've been stung, time and again by asyncio.create_task() swallowing exceptions[1], and functions not telling callers about background tasks[2].

For others looking to NOT rewrite all their code using a 3rd party event loop, here's a simple reproduction of nursery's behaviour in raw asyncio -

Hopefully, this will help lift the curse of asyncio :)

[EDIT] A library is also available - https://github.com/Tygs/ayo (with amazing operator overload)

  async def main():
      async with Nursery() as ny:
          ny.start_soon(a_1(), a_2(), ..., a_n())
          ny.start_soon(b_1(), b_2(), ..., b_n())
          .
          .
          .
          ny.start_soon(x_1(), x_2(), ..., x_n())


  class Nursery:
      def __init__(self):
          self.tasks = set()
  
      def start_soon(self, *coros: typing.Coroutine):
          for coro in coros:
              self.tasks.add(asyncio.create_task(coro))
  
      async def __aenter__(self):
          return self
  
      async def __aexit__(self, *args):
          try:
              while self.tasks:
                  tasks = self.tasks
                  self.tasks = set()
  
                  done, pending = await asyncio.wait(
                      tasks, return_when=asyncio.FIRST_COMPLETED
                  )
  
                  try:
                      for task in done:
                          await task
                  finally:
                      self.tasks |= pending
          finally:
              for task in self.tasks:
                  task.cancel()
[1] https://stackoverflow.com/questions/60287285/starlette-async...

[2] https://github.com/encode/starlette/issues/947


trio_asyncio lets you write trio code that uses asyncio libraries.


Thanks for the pointer, hadn't heard of trio. Will check it out.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: