如何在 tkinter 的线程中通过 websocket 运行 发送消息?
How can I send a message down a websocket running in a thread from tkinter?
我有一个服务器脚本 运行ning:
async def give_time(websocket,path):
while True:
await websocket.send(str(datetime.datetime.now()))
await asyncio.sleep(3)
start_server = websockets.serve(give_time, '192.168.1.32', 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
工作正常,每 3 秒发送一次当前时间。
我可以从 运行 代码的客户端接收到该字符串:
async def hello(): #takes whatever text comes through the websocket and displays it in the socket_text label.
async with websockets.connect('ws://wilsons.lan:8765') as ws:
while True:
text = await ws.recv()
logger.info('message received through websocket:{}'.format(text))
socket_text.configure(text=text) #socket_text is a tkinter object
loop = asyncio.new_event_loop()
def socketstuff():
asyncio.set_event_loop(loop)
asyncio.get_event_loop().run_until_complete(hello())
t = threading.Thread(target=socketstuff,daemon=True)
它 运行 在一个线程中,这样我就可以 运行 tkinter.mainloop
在主线程中。这是我第一次使用threading
所以我可能理解错了,但它目前似乎有效。
我需要做的是能够根据 tkinter 事件通过 websocket 发送消息 - 目前只需单击文本框旁边的按钮,但最终会更复杂。点击部分工作正常。
我在发送邮件时遇到了很多问题。我尝试了很多不同的东西,有和没有 async
和 await
,尽管那可能只是恐慌。
主要问题似乎是我无法从 hello()
函数外部访问 ws
。这是有道理的,因为我正在使用 with
上下文管理器。但是,如果我只使用 ws = websockets.connect('ws://host')
然后我得到一个 websockets.py35.client.Connect object
,当我尝试使用 send
(或者实际上 recv
)方法时,我得到一个 object has no attribute 'send'
错误。
我希望这是足够的信息 - 很高兴 post 需要任何其他信息!
事实证明,解决这个问题的最佳方法是不使用线程。
This post帮我解决了。它表明您可以 运行,在协程中,一次 tkinter 主循环的迭代:
async def do_gui(root,interval=0.05):
while True:
root.update()
await asyncio.sleep(interval)
但是,获取 tkinter 事件以生成 websocket 消息的最佳方法是使用 asyncio.queue
。使 tkinter 回调使用 put_nowait()
将一个项目添加到队列中,并有一个 运行 与 do_gui
同时使用 await queue.get()
从中获取消息的协程队列对我有用。
我有一个服务器脚本 运行ning:
async def give_time(websocket,path):
while True:
await websocket.send(str(datetime.datetime.now()))
await asyncio.sleep(3)
start_server = websockets.serve(give_time, '192.168.1.32', 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
工作正常,每 3 秒发送一次当前时间。
我可以从 运行 代码的客户端接收到该字符串:
async def hello(): #takes whatever text comes through the websocket and displays it in the socket_text label.
async with websockets.connect('ws://wilsons.lan:8765') as ws:
while True:
text = await ws.recv()
logger.info('message received through websocket:{}'.format(text))
socket_text.configure(text=text) #socket_text is a tkinter object
loop = asyncio.new_event_loop()
def socketstuff():
asyncio.set_event_loop(loop)
asyncio.get_event_loop().run_until_complete(hello())
t = threading.Thread(target=socketstuff,daemon=True)
它 运行 在一个线程中,这样我就可以 运行 tkinter.mainloop
在主线程中。这是我第一次使用threading
所以我可能理解错了,但它目前似乎有效。
我需要做的是能够根据 tkinter 事件通过 websocket 发送消息 - 目前只需单击文本框旁边的按钮,但最终会更复杂。点击部分工作正常。
我在发送邮件时遇到了很多问题。我尝试了很多不同的东西,有和没有 async
和 await
,尽管那可能只是恐慌。
主要问题似乎是我无法从 hello()
函数外部访问 ws
。这是有道理的,因为我正在使用 with
上下文管理器。但是,如果我只使用 ws = websockets.connect('ws://host')
然后我得到一个 websockets.py35.client.Connect object
,当我尝试使用 send
(或者实际上 recv
)方法时,我得到一个 object has no attribute 'send'
错误。
我希望这是足够的信息 - 很高兴 post 需要任何其他信息!
事实证明,解决这个问题的最佳方法是不使用线程。
This post帮我解决了。它表明您可以 运行,在协程中,一次 tkinter 主循环的迭代:
async def do_gui(root,interval=0.05):
while True:
root.update()
await asyncio.sleep(interval)
但是,获取 tkinter 事件以生成 websocket 消息的最佳方法是使用 asyncio.queue
。使 tkinter 回调使用 put_nowait()
将一个项目添加到队列中,并有一个 运行 与 do_gui
同时使用 await queue.get()
从中获取消息的协程队列对我有用。