У меня есть следующий код:
import asyncio
import threading
import time
q = asyncio.Queue()
async def ping():
while True:
await asyncio.sleep(10)
print("ping")
async def rcv():
while True:
item = await q.get()
print("got item")
async def run():
tasks = [asyncio.ensure_future(ping()), asyncio.ensure_future(rcv())]
await asyncio.wait(tasks, return_when="FIRST_EXCEPTION")
loop = asyncio.get_event_loop()
def run_loop():
asyncio.set_event_loop(loop)
loop.run_until_complete(run())
threading.Thread(target=run_loop).start()
while True:
time.sleep(2)
q.put_nowait("item")
print("item added")
Я ожидал, что каждые 2 секунды (каждый раз, когда элемент добавляется в очередь), я увижу вывод:
item added
sleeping 2 seconds
got item
и каждые 10 секунд я также увижу ping
.
Тем не менее, это вывод, который я получаю (повторяя):
sleeping 2 seconds
item added
sleeping 2 seconds
item added
sleeping 2 seconds
item added
sleeping 2 seconds
item added
sleeping 2 seconds
got item
got item
got item
got item
ping
item added
sleeping 2 seconds
...
Кажется, что часть item = await q.get()
также asyncio.sleep(10)
из функции ping
.
Что я упустил? и как я могу исправить код, чтобы получить ожидаемый результат?
Спасибо!
Что я упустил? и как я могу исправить код, чтобы получить ожидаемый результат?
Поскольку вы запускаете цикл событий в отдельном потоке, вам необходимо изменить q.put_nowait("item")
на:
loop.call_soon_threadsafe(q.put_nowait, "item")
Причина в том, что асинхронный код (намеренно) не является потокобезопасным, поэтому использование put_nowait
не уведомляет цикл событий о том, что новый элемент был установлен в очередь.