user3599803
user3599803

Reputation: 7044

python asyncio - cleanup event loop on ctrl+c? and close() vs stop()

Code:

loop = asyncio.get_event_loop()
# add tasks to the loop
# ...

# and then run the loop
try:
   loop.run_forever()
except KeyboardInterrupt:
   print(loop)
   # Here I need to run a cleanup, I still need to use the event loop
   # Can I still use the event loop here? like:
   loop.run_until_complete(some_cleanup_coro())
  1. when I print the event loop in the except block, I see the output: WindowsSelectorEventLoop, with closed=False, running=False. Does it means I can't use the event loop in the except block? then how can I run a cleanup coroutine?

The run_until_complete call hangs and not running. So pressing ctrl+c does not exit and I have to close the terminal itself.

  1. What's the difference between loop.close() and loop.stop(), and should I call these? The docs say nothing about loop.stop().

My cleanup_coro() does mostly asyncio.open_connection(..) and just sends and receives one message. (From what I see, the message is not sent at all).

Upvotes: 4

Views: 5464

Answers (2)

KC.
KC.

Reputation: 3107

Does it means I can't use the event loop in the except block?

You can keep using the event loop until it closes.

So pressing ctrl+c does not exit and I have to close the terminal itself.

Why Ctrl+C doesn't work is because something keep running, so it did not give the loop a chance to accept the signal (Ctrl+C). Just like:

import asyncio

async def go():
    await asyncio.sleep(60)

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(go())

According to your last edit, I think there is a line of code blocking you before you send the message. But for me to tell you what it is, you would need to post your cleanup_coro() content. Or you can use print() to mark what happens where (i.e. which line of code is pending).

What's the difference between loop.close() and loop.stop(), and should I call these? The docs says nothing about loop.stop().

You can imagine that loop.close() and loop.stop() are similar to "next song" and "stop this song". If you don't need "this song", so play the "next one". If you want to continue the task later, use stop. However, when you don't need the running task at all, you can close the loop. Note: If any tasks is running you must stop before closing.

Upvotes: 3

dirn
dirn

Reputation: 20759

In your except block, the loop is no longer running, but not closed, so you can start it again (loop.run*). This state occurs when something calls loop.stop. asyncio will do this for you in the case of exceptions that bubble up through the code that started the loop. You can start and stop a loop as often as you’d like.

Without knowing what some_cleanup_coroutine does, or what other coroutines are still schedule with the event loop, it’s hard to say when your code is getting hung.

Calling loop.close will prevent you from starting it again. You’d need to get a new loop (asyncio.new_event_loop) if you want to do more work.

Upvotes: 1

Related Questions