Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't create new event loop after calling loop.close asyncio.get_event_loop in Python3.6.1

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.

like image 722
T. Bringazi Avatar asked Apr 27 '17 00:04

T. Bringazi


1 Answers

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)
like image 87
dirn Avatar answered Oct 04 '22 19:10

dirn