2016-12-12 4 views
2

Я начинаю с websockets и asyncio и с трудом понимаю логику. Я использовал потоки на Python в прошлом, а также AJAX вызывает Javascript (поэтому у меня есть идея концепции нескольких потоков (привязка ввода/вывода) и вызовов процедур, результаты которых действуют асинхронно).Зачем мне нужно ждать сопрограммы?

Пример сервера ниже. Моя цель состоит в том, чтобы обеспечить подключение к сети и две функции, которые будут вызываться каждые 10 секунд, не дожидаясь результатов (так точно один вызов каждые 10 секунд, независимо от того, сколько времени требуется для обработки функций).

import time 
import arrow 
import websockets 
import asyncio 

async def time1(websocket): 
    # simulation of a time intensive operation 
    time.sleep(2) 
    msg = '1 ' + arrow.now() 
    print(msg) 
    websocket.send(msg) 

async def time2(websocket): 
    # simulation of a time intensive operation 
    time.sleep(3) 
    msg = '2 ' + arrow.now() 
    print(msg) 
    websocket.send(msg) 

async def update_info(websocket, path): 
    while True: 
     now = arrow.now() 
     if not now.second % 10: 
      time1(websocket) 
     if not now.second % 10: 
      time2(websocket) 

     time.sleep(1) 

start_server = websockets.serve(update_info, 'localhost', 5678) 
asyncio.get_event_loop().run_until_complete(start_server) 
asyncio.get_event_loop().run_forever() 

Я ожидал получить, как только клиент подключится, на следующие полные 10 секунд функции будут запущены. Они завершат через 2 и 3-х секунд, затем обстреляли следующие полные 10 секунд и т.д.

Что я получил вместо этого

D:/Dropbox/dev/domotique/webserver.py:708: RuntimeWarning: coroutine 'time1' was never awaited 
    time1(websocket) 
D:/Dropbox/dev/domotique/webserver.py:710: RuntimeWarning: coroutine 'time2' was never awaited 
    time2(websocket) 

и ни одно из сообщений не было либо отправлено или распечатать.

Почему у меня есть await для сопроводителей? Я хотел бы запустить их в форму update_info и забыть о них (= оставить их для их обработки и позволить им отправлять данные через websocket). Что не так с моим подходом?

ответ

3

await эффективно соединяет ожидаемую сопрограмму с контуром события, ждет ее завершения и продолжается. Если вы не сделаете await сопрограмму, то этого не произойдет.

Если вы просто хотите запустить сопрограмму в фоновом режиме (более как Task), а затем использовать asyncio.ensure_future(my_coroutine()), который будет спин-офф с Task и позволит вам продолжить, на с другими предметами.

РЕДАКТИРОВАТЬ: Получение новичков для асинхронного вызова заключается в том, что если у вас есть несколько запущенных задач, то, если в задачах нет внутренних операторов await, цикл событий будет зависеть от этой задачи, если он не вернется. То, как цикл событий создает впечатление того, что он делает сразу две вещи, - это жонглирование между различными битами кода. Операторы await представляют собой точки, между которыми цикл событий может выполнять жонглирование. Поэтому, когда один фрагмент кода ожидает, еще один фрагмент кода запускается для запуска. Как только эта часть кода попадает в await, тогда следующий фрагмент кода в составе получает добро и т. Д. Другими словами, помните о том, где вы размещаете свой awaits, и создавайте свой код таким образом что длинные биты кода не блокируют более динамические компоненты, которые извлекают выгоду из async.

Смежные вопросы