你的 pynput 和 asyncio 东西有多个线程。要跨线程共享数据,您需要一个线程安全的容器。一种选择是 python 的 queue 模块。
一个更好的选择——从 asyncio 的角度来看——正如 user4815162342 在 cmets 中指出的那样,是使用 asyncio 的 Queue 和来自其他线程的 asyncio 的 event_loop 上的 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()
使用标准 queue.Queue 的旧示例。
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>