Невозможно создать новый цикл событий после вызова loop.close asyncio.get_event_loop в Python3.6.1

В Python3.6.1 после вызова loop.close() в цикле, полученном из asyncio.get_event_loop(), можно ли создать новый цикл?

Я просмотрел другие сообщения с ответами на правильное закрытие цикла, а также на то, как использовать task.cancel(), но не смог использовать ни один из этих примеров таким образом, чтобы позволить создать новый цикл после первый был закрыт. Я также пытался явно установить executor и позже вызвать executor.shutdown(wait=True), но это не помогло. Я также пробовал 'del loop' и множество других вещей.

В документации указано, что закрытие цикла событий является идемпотентным и необратимым. Означает ли это также, что новый цикл не может быть создан?

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()

`

Любые попытки ответить на мой вопрос будут оценены.

В качестве альтернативы, было бы дурным тоном создать цикл событий, использовать его для различных целей, а затем просто закрыть этот цикл, когда долго работающая программа вот-вот завершится? Это просто кажется неправильным.


person T. Bringazi    schedule 27.04.2017    source источник


Ответы (1)


asyncio.get_event_loop возвращает текущий цикл. Он не обращает внимания на состояние цикла. Если вам нужен новый цикл после закрытия одного, вы можете использовать asyncio.new_event_loop.

Имейте в виду, что получение нового цикла не повлияет на последующие вызовы get_event_loop. Если вы хотите, чтобы возвращался ваш новый цикл вместо исходного (тем более, что вы, вероятно, закрыли его), вам нужно будет вызвать asyncio.set_event_loop самостоятельно.

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)
person dirn    schedule 27.04.2017
comment
Большое тебе спасибо!!! Это отлично сработало. Раньше я пробовал new_event_loop, но, должно быть, во время этого эксперимента я сделал что-то не так. - person T. Bringazi; 27.04.2017
comment
Я забыл упомянуть set_event_loop. Это может быть связано с проблемами, с которыми вы столкнулись. Я обновил ответ, чтобы включить его. - person dirn; 27.04.2017
comment
Для потомков: большинство функций в пакете asyncio получают необязательный параметр loop. - person turdus-merula; 11.02.2020