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

exactly -

The problem is that there are three logical states that need three different actions

1. if nothing done yet: start async computation

2. if async computation in progress: wait for it

3. return result as computaton done

Atomicity in the sense that no other Python code can run during a setdefault, is not relevant.

Waiting for something that is running in another loop actually isn't easy either; I'm not sure that Python really allows it - won't you get an error:

   The future belongs to a different loop than the one specified as the loop argument


This code creates that error by trying to wait in two threads in two loops. If the future is finished, it is fine to wait for it.

Having multiple loops waiting for each other is pretty complex to debug.

  import asyncio
  import threading

  future = None

  def p(msg):
    print(f"{msg}: {threading.get_ident()}, event loop: {id(asyncio.get_running_loop())}")


  async def one_time_setup():
    p('one_time_setup start')
    await asyncio.sleep(1)
    p('one_time_setup done')

  async def maybe_initialize():
    global future
    if not future:
        future = asyncio.create_task(one_time_setup())
        p('waiting start')
        await future
        p('waiting done')

  def worker():
    new_loop = asyncio.new_event_loop()
    asyncio.set_event_loop(new_loop)
    new_loop.run_until_complete(maybe_initialize())

  number_of_threads = 2
  for _ in range(number_of_threads):
    threading.Thread(target=worker).start()
this prints

  RuntimeError: Task <Task pending coro=<maybe_initialize() running at test.py:20> cb=[_run_until_complete_cb() at /Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py:158]> got Future <Task pending coro=<one_time_setup() running at test.py:11> cb=[<TaskWakeupMethWrapper object at 0x10cafdeb8>()]> attached to a different loop


You can do this in python using `Future` or `Task`. For example, with `asyncio.ensure_future`.




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

Search: