Skip to content

Instantly share code, notes, and snippets.

@tfarago
Created September 20, 2022 15:03
Show Gist options
  • Save tfarago/389d4960cf405cdd0ea166471f760f03 to your computer and use it in GitHub Desktop.
Save tfarago/389d4960cf405cdd0ea166471f760f03 to your computer and use it in GitHub Desktop.
asyncio coroutines not running through
import asyncio
RUNNING = set([])
async def coro(name, howlong=5, raise_exc=None):
print('start', name)
if raise_exc:
raise raise_exc
try:
RUNNING.add(name)
await asyncio.sleep(howlong)
print('slept', name, howlong)
RUNNING.remove(name)
except BaseException as e:
print(f'except {e.__class__.__name__} start', name)
await asyncio.sleep(0.2)
if name in RUNNING:
RUNNING.remove(name)
print(f'except {e.__class__.__name__} finished', name)
raise
return name
async def gather_or_wait(use_gather=True, raise_exc=None):
loop = asyncio.get_running_loop()
try:
tasks = [
loop.create_task(coro(1, howlong=1)),
loop.create_task(coro(2, howlong=2)),
loop.create_task(coro(3, howlong=3, raise_exc=raise_exc)),
]
if use_gather:
task = asyncio.gather(*tasks, return_exceptions=False)
await task
else:
await asyncio.wait(tasks, return_when=asyncio.ALL_COMPLETED)
except BaseException as e:
print(f'{e.__class__.__name__} in gather_or_wait')
for task in tasks:
task.cancel()
# Actually it doesn't matter if we use gather or wait here. With Approach 1 we still
# don't run through and with Approach 3 we do.
if use_gather:
await asyncio.gather(*tasks, return_exceptions=True)
else:
await asyncio.wait(tasks, return_when=asyncio.ALL_COMPLETED)
def main():
global RUNNING
# Approach 1: doesn't work
try:
asyncio.run(gather_or_wait(use_gather=True, raise_exc=KeyboardInterrupt))
except KeyboardInterrupt:
print('KeyboardInterrupt in main')
print('run gather: unfinished:', RUNNING)
RUNNING = set([])
print('\n------------------------------\n')
# Approach 2: doesn't work
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
task = loop.create_task(gather_or_wait(use_gather=True, raise_exc=KeyboardInterrupt))
try:
loop.run_until_complete(task)
except KeyboardInterrupt:
print('KeyboardInterrupt in main')
task.cancel()
loop.run_until_complete(task)
loop.stop()
loop.close()
print('manual gather: unfinished:', RUNNING)
RUNNING = set([])
print('\n------------------------------\n')
# Approach 3: works
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
task = loop.create_task(gather_or_wait(use_gather=False, raise_exc=KeyboardInterrupt))
try:
loop.run_until_complete(task)
except KeyboardInterrupt:
print('KeyboardInterrupt in main')
task.cancel()
loop.run_until_complete(task)
loop.stop()
loop.close()
print('manual wait: unfinished:', RUNNING)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment