2016-12-12 135 views
2

我開始使用websockets和asyncio,並且很難理解背後的邏輯。過去我在Python上使用了線程以及Javascript上的AJAX調用(所以我對多線程(I/O綁定)的概念有所瞭解,並調用了結果異步執行的過程)。爲什麼我需要等待協程?

示例服務器如下。我的目標是提供一個websocket連接和兩個函數,這些函數將每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,那麼排隊中的下一段代碼就會繼續運行等等。換句話說,請注意您將awaits放在哪裏,並以這種方式設計代碼長時間運行的代碼不會阻擋從異步中受益的更多動態組件。