Python Asyncio: запуск цикла без созданной задачи - PullRequest
1 голос
/ 16 марта 2019

Может ли кто-нибудь объяснить мне, почему я не могу выполнить свои задачи, если я запускаю цикл без каких-либо добавленных задач раньше? (Python 3.7)

import asyncio
import threading    

def run_forever(loop):
    loop.run_forever()

async def f(x):
    print("%s executed" % x)

# init is called first
def init():
    print("init started")

    loop = asyncio.new_event_loop()

    # loop.create_task(f("a1")) # <--- first commented task

    thread = threading.Thread(target=run_forever, args=(loop,))
    thread.start()

    loop.create_task(f("a2")) # <--- this is not being executed

    print("init finished")

Если я оставлю комментарий к # loop.create_task(f("a1")), выполнение будет:

init started
init finished

Некомментированное исполнение:

init started
init finished
a1 executed
a2 executed

Почему так? Я хотел создать цикл и добавить задачи в будущем.

1 Ответ

2 голосов
/ 16 марта 2019

Если явно не указано иное, asyncio API не является поточно-ориентированным . Это означает, что вызов loop.create_task() из потока, отличного от того, в котором выполняется цикл обработки событий, не будет правильно синхронизироваться с циклом.

Чтобы отправить задачу в цикл событий из стороннего потока, вместо этого необходимо вызвать asyncio.run_coroutine_threadsafe:

asyncio.run_coroutine_threadsafe(f("a2"), loop)

Это пробудит цикл, чтобы предупредить о прибытии нового задания, а также вернет concurrent.futures.Future, который можно использовать для получения результата сопрограммы.

...