Python将数据发送到Websockets

时间:2019-12-16 00:50:08

标签: python python-3.x websocket python-asyncio

我正在尝试使用超简单的websocket将全局鼠标光标位置流式传输到Web客户端。

这两种情况都发生了,并且我的客户端(使用JS)工作正常,但是我不知道如何连接它们;每当调用move()时,我都想发送一个websocket消息,但是我尝试的所有操作都会引发错误。

此代码打印出鼠标位置并运行websocket,但是如何使两者相互“交谈”?

import asyncio
import websockets
from pynput import mouse

def onmove(x, y):
    print(x,y)

async def socket_handler(websocket, path):
    while True:
        message = await websocket.recv()
        print(f"Received {message}")

        resp = f'WS Message Was: {message}'
        await websocket.send(resp)


listener = mouse.Listener(on_move = onmove)
listener.start()

start_server = websockets.serve(socket_handler, "127.0.0.1", 5000)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

我觉得肯定有一个非常明显的答案,我只是不了解异步和事件循环而已

1 个答案:

答案 0 :(得分:1)

您有很多线程与pynput和asyncio一起运行。要跨线程共享数据,您需要一个线程安全的容器。一种选择是python的queue模块。

从asyncio的角度来看,更好的选择(如user4815162342的注释所指出)是在您的其他线程的asyncio的event_loop上使用asyncio的Queue和call_soon_threadsafe。这是一个示例:

import asyncio
import json
import websockets
from pynput import mouse

q = asyncio.Queue()

def onmove(x, y):
    loop.call_soon_threadsafe(q.put_nowait, (x,y))

async def socket_handler(websocket, path):
    while True:
        message = await q.get()
        await websocket.send(json.dumps(message))

loop = asyncio.get_event_loop()
start_server = websockets.serve(socket_handler, "127.0.0.1", 5000)
loop.run_until_complete(start_server)

listener = mouse.Listener(on_move = onmove)
listener.start()
loop.run_forever()

使用标准队列的旧示例。

example_server.py

import asyncio
import queue
import json
import websockets
from pynput import mouse

q = queue.SimpleQueue()

def onmove(x, y):
    try:
        print("Putting: {0}".format((x,y)))
        q.put((x,y), block=False)
    except q.Full:
        print("Dropped coords: {0}".format((x,y)))

async def getCoords():
    coords = None
    try:
        coords = q.get(block=False)
    except queue.Empty:
        # print("QUEUE EMPTY")
        pass
    return coords

async def socket_handler(websocket, path):
    while True:
        message = await getCoords()
        if message:
            await websocket.send(json.dumps(message))

listener = mouse.Listener(on_move = onmove)
listener.start()

loop = asyncio.get_event_loop()
start_server = websockets.serve(socket_handler, "127.0.0.1", 5000)
loop.run_until_complete(start_server)
loop.run_forever()

example_client.html

<html>
<head>
<script
  src="https://code.jquery.com/jquery-3.4.1.min.js"
  integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
  crossorigin="anonymous"></script>
<script>
$(function() {
   var exampleSocket = new WebSocket("ws://127.0.0.1:5000");
   exampleSocket.onmessage = function (event) {
         var coords = JSON.parse(event.data);
         $('#x').html(coords[0]);
         $('#y').html(coords[1]);
   };
});
</script>
</head>
<body>
<p>X: <span id="x"></span></p>
<p>Y: <span id="y"></span></p>
</body>
</html>