My client application uses a Kivy
GUI (Kivy has its own event loop) and connects to the server using the WebSocket protocol with Tornado
(Tornado also has an event loop). That's why the connection part is asynchronous.
I want the user to interact with the UI while a Tornado client is running an infinite asynchronous loop of listening for server messages.
Here's some example code:
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()
GUI
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()
Apparently, since the Tornado's event loop has started earlier, it has taken over the program flow and now no GUI window appears.
I execute the GUI file and the execution hangs after the RequestSender().run()
, so build
never returns.
Searching on this case provided little to no information, except for this Google Groups post. Kivy's documentation only mentions Twisted.
I tried putting the Kivy event loop into slave mode and running GUI updates from Tornado's event loop, but that didn't work because apparently a call EventLoop.idle()
of Kivy's event loop isn't enough to keep the GUI application running.
What else could be done here?
I found this question trying to do the same thing, and opted for two separate processes instead; one Kivy GUI and one Tornado (Server, in my case). I have the two communicate using
multiprocessing.connection
as explained well in this SO answerIf you have large and complex data to pass between the two, perhaps this is less than ideal, but for simple messages it works well. You also have the advantage of running without the UI, and running the UI on a separate machine.