2016-12-10 2 views
3

В моем клиентском приложении используется графический интерфейс Kivy (у Kivy есть собственный цикл событий) и подключается к серверу с использованием протокола WebSocket с Tornado (у Tornado также есть цикл событий). Вот почему соединение является асинхронным.
Я хочу, чтобы пользователь взаимодействовал с пользовательским интерфейсом, а клиент Tornado запускал бесконечный асинхронный цикл прослушивания сообщений сервера.Как запустить цикл событий Tornado вместе с графическим интерфейсом Kivy?

Вот пример кода:
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() 

По-видимому, так как цикл событий смерча начал раньше, переняла программы поток, и теперь не появляется окно GUI.
Я запускаю файл GUI, и выполнение зависает после RequestSender().run(), поэтому build никогда не возвращается.

Поиск по этому случаю предоставлен практически без информации, за исключением this Google Groups post. Документация Kivy упоминается только в Twisted.

Я попытался включить цикл событий Kivy в подчиненный режим и запустить обновления графического интерфейса из цикла событий Tornado, но это не сработало, потому что, по-видимому, вызов цикла EventLoop.idle() цикла событий Kivy недостаточен для работы приложения GUI.

Что еще можно сделать здесь?

+0

Я думаю, что подход, сделанный с извращенным, состоит в том, чтобы включить event -oo приключений Kivy в Twisted's eventloop. Возможно, с Торнадо можно добиться того же. – inclement

+0

@inclement неясно, как цикл Twisted event управляется, поскольку это пакет специально для Twisted. Вместо этого я попробовал обратный подход: нужно, чтобы цикл событий Kivy запускался как ведомый и цикл событий Tornado для вызова 'EventLoop.idle()' на каждой итерации. Окно успешно загружается, но затем приложение зависает. Подробнее в редакторе – Leva7

+0

Я думаю, что запуск двух циклов событий с двумя отдельными потоками может быть намного проще в обработке, чем попытка их интеграции. – Nykakin

ответ

0

Я нашел этот вопрос, пытаясь сделать то же самое, и вместо этого выбрал два отдельных процесса; один Kivy GUI и один Tornado (сервер, в моем случае). У меня есть две связи, использующие multiprocessing.connection, как хорошо объяснено в this SO answer

Если у вас есть большие и сложные данные для прохождения между ними, возможно, это не идеальный вариант, но для простых сообщений он работает хорошо. У вас также есть преимущество без использования пользовательского интерфейса и запуск пользовательского интерфейса на отдельной машине.

Смежные вопросы