如何在 Kivy GUI 旁边运行 Tornado 事件循环?

Posted

技术标签:

【中文标题】如何在 Kivy GUI 旁边运行 Tornado 事件循环?【英文标题】:How to run the Tornado event loop alongside a Kivy GUI? 【发布时间】:2017-04-25 19:23:54 【问题描述】:

我的客户端应用程序使用Kivy GUI(Kivy 有自己的事件循环)并使用带有Tornado 的 WebSocket 协议连接到服务器(Tornado 也有一个事件循环)。这就是连接部分是异步的原因。 我希望用户在 Tornado 客户端运行无限异步循环以侦听服务器消息时与 UI 交互。

以下是一些示例代码:client_test.py

from tornado.ioloop import IOLoop
from tornado.websocket import websocket_connect

class RequestSender:
    url = 'server url here (no scheme)'

    async def _connect(self):
        self.conn = await websocket_connect('wss://' + self.url, io_loop=self.ioloop)
        self.ioloop.add_callback(self._listen)

    async def _listen(self):
        while True:
            print(await self.conn.read_message())

    def __init__(self):
        self.ioloop = IOLoop.current()
        self.ioloop.add_callback(self._connect)

    def run(self):
        self.ioloop.start()

图形界面

from kivy.app import App
from kivy.uix.label import Label
from client_test import RequestSender

class TestApp(App):
    def build(self):
        RequestSender().run()
        return Label(text = "hello")

TestApp().run()

显然,由于 Tornado 的事件循环更早开始,它已经接管了程序流程,现在没有出现 GUI 窗口。 我执行了 GUI 文件,在RequestSender().run() 之后执行挂起,所以build 永远不会返回。

除了this Google Groups post 之外,搜索此案例几乎没有提供任何信息。 Kivy 的文档只提到了Twisted。

我尝试将 Kivy 事件循环置于从属模式并从 Tornado 的事件循环运行 GUI 更新,但这不起作用,因为 Kivy 事件循环的调用 EventLoop.idle() 显然不足以保持 GUI 应用程序运行。

这里还能做什么?

【问题讨论】:

我认为扭曲的方法是让 Kivy 的事件循环驱动扭曲的事件循环。也许你可以用 Tornado 实现同样的目标。 @inclement 不清楚 Twisted 事件循环是如何被驱动的,因为它是一个专门为 Twisted 设计的包。我尝试了一种向后的方法:让 Kivy 事件循环作为从属运行,Tornado 事件循环在每次迭代时调用EventLoop.idle()。窗口成功加载,但随后应用程序冻结。更多细节在编辑中 我认为使用两个单独的线程运行两个事件循环可能比尝试将它们集成起来更容易处理。 @Nykakin 是的,我试过了,而且更容易。问题是在 Tornado 线程上进行一些繁重的计算期间,Kivy 应用程序停止响应。这可以解决吗? @Leva7 单独线程上的繁重计算不应影响主线程中的 GUI 事件循环。我的猜测是您以阻塞方式处理两个线程之间的通信。您可能应该使用 queue.Queue 类并调用 get 方法并设置一些超时设置。考虑将您的代码放在一个单独的问题中。 【参考方案1】:

我发现这个问题试图做同样的事情,并选择了两个单独的进程;一个 Kivy GUI 和一个 Tornado(在我的例子中是服务器)。我让两者使用multiprocessing.connection 进行通信,正如this SO answer 中所解释的那样

如果您要在两者之间传递大量而复杂的数据,这可能不太理想,但对于简单的消息来说效果很好。您还可以在没有 UI 的情况下运行,并在单独的机器上运行 UI。

【讨论】:

以上是关于如何在 Kivy GUI 旁边运行 Tornado 事件循环?的主要内容,如果未能解决你的问题,请参考以下文章

无法在 Ubuntu Wily 上运行 Kivy

如何制作kivy文件的单独模块并与python文件集成

您如何使用 Kivy GUI 访问其他类方法和函数?

Kivy GUI 冻结

Python Kivy:正确启动更新 GUI 元素的后台进程

Kivy GUI (Python) 在尝试更新屏幕时陷入分段错误