這次筆記是修正Websockets改為15版的寫法
因為把Python昇級,加上Websockets自己也升級
所以之前這篇使用Python的websockets套件控制樹莓派的寫法不能用了
要改新的寫法
這部分其實很簡單
但我因為太久沒碰這隻程式忘光了基礎
還是搞了不短的一段時間(花了半天 Orz)
為了之後能快速使用,留下這個記錄吧
廢話不多說,直接用原始碼說明
原本是長這樣子
import asyncio import websockets import pathlib # 設定全域變數 mission_lists = [] #無限循環用的伺服程式 async def custom_server(): while True: #避免一直陷在迴圈中無法異步化,會中止5秒,讓其它websocket任務可以動作 await asyncio.sleep(5) #清單不為零,開始執行任務清單 if len(mission_lists) > 0: app_log.info('start mission') mission = mission_lists.pop() await do_mission(mission) #主動發送訊息用的生產者程式 async def message_handler(websocket, path): while True: message = "目前處理狀況" await websocket.send(message) await asyncio.sleep(3) #3秒的間隔發送 #接收並處理使用者訊息的生產者程式 async def cmd_handler(websocket, path): async for message in websocket: #取得送進來的訊息 data = json.loads(message) #處理訊息轉為任務 mission = process(data) #加入任務清單 mission_lists.append(mission) #Websocket伺服器主程式, 只有消費者與生產者 async def main_handler(websocket, path): consumer_task = asyncio.ensure_future( cmd_handler(websocket, path)) producer_task = asyncio.ensure_future( message_handler(websocket, path)) done, pending = await asyncio.wait( [consumer_task, producer_task], return_when=asyncio.FIRST_COMPLETED, ) #當沒有websocket連線時,停止任務執行 for task in pending: task.cancel() #加入SSL通信功能 ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) localhost_pem = pathlib.Path(__file__).with_name("localhost.pem") ssl_context.load_cert_chain(localhost_pem) #設定websocket伺服器 start_server = websockets.serve(main_handler, "0.0.0.0", 8765, ssl=ssl_context) #將websockets伺服任務丟入異步的迴圈中 asyncio.get_event_loop().run_until_complete(start_server) #補上自己額外的任務,丟入異步的迴圈中 asyncio.get_event_loop().run_until_complete(custom_server()) #讓異步的迴圈一直執行 asyncio.get_event_loop().run_forever()
改版成15版後變成這個樣子
import asyncio import websockets import pathlib #設定全域變數 mission_lists = [] #無限循環用的伺服程式 #這裡都不用變 async def custom_server(): while True: #避免一直陷在迴圈中無法異步化,會中止5秒,讓其它websocket任務可以動作 await asyncio.sleep(5) #清單不為零,開始下載 if len(mission_lists) > 0: app_log.info('start mission') mission = mission_lists.pop() await do_mission(mission) #主動發送訊息用的生產者程式 #這裡就輸入變數取消path這項 async def message_handler(websocket): #取消path while True: message = "目前處理狀況" await websocket.send(message) await asyncio.sleep(3) #3秒的間隔發送 #接收並處理使用者訊息的生產者程式 #一樣,輸入變數取消path這項 async def cmd_handler(websocket): #取消path async for message in websocket: data = json.loads(message) mission = process(data) mission_lists.append(mission) #Websocket伺服器主程式, 只有消費者與生產者 #一樣只有取消path的輸入,其它不變 async def main_handler(websocket): consumer_task = asyncio.ensure_future( cmd_handler(websocket)) producer_task = asyncio.ensure_future( message_handler(websocket)) done, pending = await asyncio.wait( [consumer_task, producer_task], return_when=asyncio.FIRST_COMPLETED, ) #當沒有websocket連線時,停止任務執行 for task in pending: task.cancel() #新的伺服啟動寫法 #建立異步執行專用函數,如果沒有其它要跑的項目,直接用main也行 async def main_server(): #加入SSL通信功能 ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) localhost_pem = pathlib.Path(__file__).with_name("localhost.pem") ssl_context.load_cert_chain(localhost_pem) # 異步建立自己的伺服任務 asyncio.create_task(custom_server(mission_lists)) #設定websocket伺服器 async with websockets.serve( main_handler, "0.0.0.0", 8765, ssl=ssl_context ) as server: # 設定這個伺服器持續運行 await server.serve_forever() #以異步運轉,正式執行設定好的websockets伺服器 asyncio.run(main_server())
主要的差異其實是Websockets伺服的啟動
改用常用的異步執行asyncio.run去跑
然後還有函數的引數變不同了,那個path被拿掉了
原本消費者與生產者的主架構是沒什麼差異的
新的說明可以看下面官方的頁面
https://websockets.readthedocs.io/en/stable/howto/patterns.html
所以說改新寫法真的很簡單
沒有留言:
張貼留言