Форум сайта python.su
0
Добрый день.
Есть ли способ подружить pyqt и asyncio?
Задача: из gui сделать две кнопки - старт и стоп сервера. Код сервера запускается из QThread. Сделан на async/await. По отдельности все ок. Вместе не получается.
#MainWindowQT def btn_start(self): today = datetime.datetime.today() self.label_4.show() self.label_5.hide() self.btnStart.setDisabled(True) self.btnStop.setEnabled(True) self.serverThread.start() self.textBrowser.append(str(today.strftime("%Y-%m-%d %H:%M:%S ") + 'INFO Сервер запущен'))
#ThreadQT from PyQt5 import QtCore import Model.Server import asyncio class ThreadServer(QtCore.QThread): sigServ = QtCore.pyqtSignal(str) def __init__(self,parent=None): QtCore.QThread.__init__(self,parent) self.running = False def run(self): self.running = True s = Model.Server.Server() while self.running: print('1' + str(self.running)) asyncio.run(s.serverInit())#Отсюда нет возврата управления, что логично в общем то QtCore.QThread.sleep(1) print('2' + str(self.running)) s.stop() print("stop")
#Server import asyncio class Server(): def __init__(self): self.host = '127.0.0.1' self.port = '9001' async def serverInit(self): self.server = await asyncio.start_server(self.readFromServer, self.host, self.port) await self.server.serve_forever() async def readFromServer(self,reader, writer): data = await reader.read(1024) print(f'Received: {data.decode()!r}') async def stop(self): self.server.close()
Отредактировано Amperandus1 (Фев. 27, 2020 11:08:17)
Офлайн
44
не очень дружу с python и qt но вот такие есть соображения ..
Программирование на Python, том 1, 4-е издание. Марк Лутц
Взаимодействия между процессами…………………………………316
Анонимные каналы………………………………………………..318
Именованные каналы (fifo)……………………………………….331
Сокеты: первый взгляд…………………………………………….335
Сигналы………………………………………………………………340
Обзор tkinter…………………………………………………………….490
и вставьте ссылку на его url Офлайн
186
self.running = True s = Model.Server.Server() while self.running: print('1' + str(self.running)) asyncio.run(s.serverInit())#Отсюда нет возврата управления, что логично в общем то QtCore.QThread.sleep(1) print('2' + str(self.running)) s.stop()
Отредактировано Rodegast (Фев. 27, 2020 15:54:56)
Офлайн
0
Это меня устроит вполне. Он не возвращает управление сейчас в while. нужно решить эту проблему
Лутца я читал. Там немного не про то и устарело малость. Про tkinter читал опять же что лучше и не начинать с ним работать. Две кнопки это сейчас. В планах было дописать до большего функционала.
Пробовал с try except с выбросом исключений - тоже не взлетело.
Офлайн
44
Amperandus1а я еще нет (еще не все т.е. пока читаю), но это не повод для гордости (для меня) … но это такое … неважное
Лутца я читал
Amperandus1попробую сказать более ясно …
В принципе останется вариант работы без GUI из консоли - там все ок будет, но хотелось бы с кнопочками и окном.
и вставьте ссылку на его url Отредактировано AD0DE412 (Фев. 27, 2020 17:38:54)
Офлайн
253
Amperandus1
По отдельности все ок. Вместе не получается.
Amperandus1Так непонятно что именно не получается. Выполнение треда останавливается. Так и должно быть. В чем проблема?
Выполнение останавливается на asyncio.run(s.serverInit())
Amperandus1А понимать особо нечего. В GUI есть event loop. В asyncio свой event loop. Если их будет оба, то будут трудности с их синхронизацией. библиотеки типа asyncqt делают общий event loop для всех асинхронных событий. Пользуйтесь и будет вам счастье.
не особо понятные мне, библиотеки (например, asyncqt).
Офлайн
0
Значит придется копать в сторону библиотек. Просто хотел узнать - есть ли другие варианты (видимо нет).
Офлайн
253
Amperandus1Как раз вариантов бесконечно много. НО!! Вы не написали почему считаете что оно не работает. Вы не написали как хотите эксплуатировать ваше приложение (способ обмена данными с кнопочками). А любые способы требуют понимания того что вы делаете и зачем.
Просто хотел узнать - есть ли другие варианты (видимо нет).
Офлайн
0
Есть основной поток QT с кнопочками. Из него я запускаю QThread - второй поток, в котором запускаю асинхронный сервер. Вот в него мне бы хотелось получать обратно управление потому что хочу иметь возможность останавливать сервер. Потоки как раз сигналами связаны между собой. А вот как связать потоки pyqt и код сервера на asyncio я пока не нашел. Запустить да - получается, управлять - нет.
Есть еще QTcpSocket… в общем нужно выяснить в какую сторону лучше копать.
Смог остановить север. Не могу запустить второй раз. Один черт не возвращается управление… надо думать
Отредактировано Amperandus1 (Фев. 28, 2020 09:12:51)
Офлайн
0
Не знаю насколько правильное решение с прерыванием потока, но работает.
class ThreadServer(QtCore.QThread): sigServ = QtCore.pyqtSignal(str) def __init__(self,parent=None): QtCore.QThread.__init__(self,parent) self.running = False self.s = Model.Server.Server() def run(self): print('start') asyncio.run(self.s.serverInit()) print('2') def stop(self): self.s.stop() self.terminate()
import asyncio class Server(): def __init__(self): self.host = '127.0.0.1' self.port = '9001' async def serverInit(self): self.server = await asyncio.start_server(self.readFromServer, self.host, self.port) await self.server.serve_forever() async def readFromServer(self,reader, writer): data = await reader.read(1024) print(f'Received: {data.decode()!r}') def stop(self): self.server.close()
Офлайн