5

In Python3.6.1 after calling loop.close() on a loop obtained from asyncio.get_event_loop(), can a new loop be created?

I've looked at other posts with answers for properly closing a loop, and also how to use task.cancel(), but have not been able to use any of those examples in a way that would let a new loop be created after the first was closed. I also tried explicitly setting executor and later calling executor.shutdown(wait=True), but that didn't help. I also tried 'del loop', and del a bunch of other things.

Documentation indicates that closing a an event loop is idempotent and irreversible. Does that also mean that a new loop cannot be created?

Here is some simple example code to demonstrate the issue: `

#!/usr/bin/env python3.6
'''
To demonstrate an issue, the following code was adapted from:
https://docs.python.org/3/library/asyncio-eventloop.html
'''
import asyncio

def hello_world(loop):
    print('Hello World')
    loop.stop()

loop = asyncio.get_event_loop()
loop.call_soon(hello_world, loop)
loop.run_forever()
# loop.close()


'''
If the commented out loop.close() above is uncommented,
the following code will fail with:
    Traceback (most recent call last):
        File "./aquestion.py", line 28, in <module>
            loopNew.call_soon(hello_world, loopNew)
        File "/Library/Frameworks/Python.framework/Versions/3.6/lib    /python3.6/asyncio/base_events.py", line 573, in call_soon
        self._check_closed()
        File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/base_events.py", line 357, in _check_closed
            raise RuntimeError('Event loop is closed')
    RuntimeError: Event loop is closed

'''
loopNew = asyncio.get_event_loop()
loopNew.call_soon(hello_world, loopNew)
loopNew.run_forever()

`

Any attempts to answer my question would be appreciated.

Alternatively, would it be bad form to create an event loop, use it for a variety of purposes, and then just close that loop when the long running program is about to exit? This just seems wrong.

1 Answer 1

14

asyncio.get_event_loop returns the current loop. It pays no attention to the state of the loop. If you need a new loop after closing one, you can use asyncio.new_event_loop.

Be aware that getting a new loop won't affect subsequent calls to get_event_loop. If you'd like that to return your new loop instead of the original one (especially since you've probably closed it), you'll need to call asyncio.set_event_loop yourself.

import asyncio

async def f():
    await asyncio.sleep(0)

loop = asyncio.get_event_loop()
loop.run_until_complete(f())
loop.close()

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you very much!!! That worked great. I had tried new_event_loop earlier, but I must have done something wrong during that experiment.
I neglected to mention set_event_loop. That may be related to the problems you ran into. I've updated the answer to include it.
For posterity - most functions in package asyncio receive the optional parameter loop.

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.