22

The Story:

I am currently looking through the asyncio basic examples, in particular this one - the simplest possible HTTP client. The main function starts an event loop, runs until the data fetching is complete and closes the event loop:

def main():
    loop = get_event_loop()
    try:
        body = loop.run_until_complete(fetch())
    finally:
        loop.close()
    print(body.decode('latin-1'), end='')

But, the code also works if I omit the loop.close():

def main():
    loop = get_event_loop()
    body = loop.run_until_complete(fetch())
    print(body.decode('latin-1'), end='')

The Question:

While there is an example, the question is a generic one - what can potentially go wrong if one would forget to close the asyncio event loop? Is the event loop going to be always implicitly closed?

4
  • 2
    You'll leak resources. Commented Dec 19, 2016 at 21:51
  • what do you think is implicitly closing it? I'd think garbage collection which you'd only be able to rely on when the program ends, how long does your program run after finishing with the event loop until the program finishes? Commented Dec 19, 2016 at 22:17
  • @FilipHaglund thanks. Can you think of a way to test/demonstrate that? Commented Dec 21, 2016 at 7:27
  • 1
    (Keep in mind the link you have supplied is for asyncio for python 3.3 and was not updated to python 3.5/3.6.) Commented Dec 24, 2016 at 22:46

1 Answer 1

16

.close() can be used by different event loop implementations to free up system resources allocated by the loop (or do anything else). If you'll take a look at the code of _UnixSelectorEventLoop, which is the (default) IOLoop used in Linux, you would find the following code:

def close(self):
    super().close()
    for sig in list(self._signal_handlers):
        self.remove_signal_handler(sig)

Here, for example, close() removes signal handlers registered with loop.add_signal_handler().

As multiple IOLoops can be started on different threads, or new IOLoops can be created after an old one is closed, (see asyncio.new_event_loop()), closing them should be considered as a good habit.

Update

Starting with Python 3.7 it is recommended to use asyncio.run instead of run_until_complete():

# Python 3.7+
def main():
    body = asyncio.run(fetch())
    print(body.decode('latin-1'), end='')

Among other things, asyncio.run takes care of finally close()ing the loop.

Sign up to request clarification or add additional context in comments.

2 Comments

Because since python 3.7 it is recommended to use asyncio.run that does this for you: github.com/python/cpython/blob/master/Lib/asyncio/runners.py
But on Windows asyncio.run will rise RuntimeError: Event loop is closed in some cases e.g. with aiohttp github.com/python/cpython/issues/83413 even on Python 3.9

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.