如何从tkinter的线程中运行websocket发送消息?

时间:2017-03-16 10:04:29

标签: python asynchronous tkinter websocket coroutine

我正在运行服务器脚本:

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。这是我曾经使用的{em>第一次时间threading因此我可能会弄错,但目前似乎有效。

我需要做的是能够根据tkinter事件向websocket发送消息 - 目前只需单击文本框旁边的按钮,但最终会发生更复杂的事情。点击部分工作正常。

我在发送邮件方面遇到了很多麻烦。无论有没有asyncawait,我都尝试过很多不同的事情,尽管这可能只是恐慌。

主要问题似乎是我无法从ws函数外部访问hello()。这是有意义的,因为我正在使用with上下文管理器。但是,如果我只是使用ws = websockets.connect('ws://host'),那么我会得到一个websockets.py35.client.Connect object我尝试使用send(或确实recv)方法,我得到object has no attribute 'send'错误。

我希望这是足够的信息 - 很乐意发布任何其他所需的信息!

1 个答案:

答案 0 :(得分:0)

事实证明,解决这个问题的最佳方法是而不是来使用线程。

This post帮助我解决了这个问题。它表明你可以在协同程序中运行tkinter mainloop的一次迭代:

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()从队列中获取消息对我有用。