如何从非异步方法发送 websocket 消息?

Posted

技术标签:

【中文标题】如何从非异步方法发送 websocket 消息?【英文标题】:How to send a websocket message from a non-async method? 【发布时间】:2020-11-07 15:16:42 【问题描述】:

我正在使用these docs 从 Python 中了解websockets

当所有事情都发生在async 方法的“内部”时,它工作正常,但我怎样才能在这些方法之外发送消息呢?在我的具体示例中,我从 Raspberry PI 上的 GPIO 引脚收到 button_pressed 事件,并且我想向所有连接的用户发送该按钮被按下的消息:

import asyncio
import websockets
import gpiozero

USERS = set()

def button_pressed():
    print("Doorbell rang!")
    if USERS:
        for user in USERS:
            print(f"Sending ring to user")
            asyncio.wait(user.send("ring"))

button = gpiozero.Button(3)
button.when_pressed = button_pressed

def register(ws):
    USERS.add(ws)

def unregister(ws):
    USERS.remove(ws)

async def doorbellsocket(websocket, path):
    register(websocket)

    try:
        async for message in websocket:
            print(f"Received message: message. Ignored.")
    finally:
        unregister(websocket)
    
print(f"Starting doorbellserv on settings.host:settings.port")
start_server = websockets.serve(doorbellsocket, settings.host, settings.port)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

代码运行,按钮按下事件被触发,Python 说它发送了一些东西,但没有任何东西到达我的客户端,就像这样简单:

function connectToServ() 
    var socket = new WebSocket(url);
    console.log("Connected to "+socket)
    socket.onmessage = function(event) 
        console.log(event.data);
    ; 

【问题讨论】:

【参考方案1】:

我不得不如此asyncio.run:

def button_pressed():
    print("Doorbell rang!")

    if USERS:
        for user in USERS:
            print(f"Sending ring to user")
            asyncio.run(user.send("ring"))

【讨论】:

以上是关于如何从非异步方法发送 websocket 消息?的主要内容,如果未能解决你的问题,请参考以下文章

Jetty Websockets - 在处理不可靠的连接时正确发送异步消息

如何永远运行异步 websocket 客户端?

如何从非异步方法调用异步方法? [复制]

一旦队列填满,WebSocket 异步发送可能会导致发送阻塞

如何使用 Tornado 监听来自多个地方的传入 websocket 消息?

Django 频道 + 在发布请求后发送 websocket 消息