Skip to content

Comment on Guide to Concurrency in Python with Asyncioparent

Comments

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.

AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.