Necessity of closing asyncio event loop explicitly

12.8k Views Asked by At

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?

1

There are 1 best solutions below

2
On BEST ANSWER

.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.