@dibanshee

Как в python и PyQt5 делать так, что бы при работе с zmq или сокетами не происходило «блокировки» окна?

Просто только начинаю изучать PyQT и очень нравится. Пытаюсь написать программу, просто ради саморазвития, прослушивания сокетов. Т.е. в окне вводятся данный хоста и порта, далее нажимается кнопка старт сервер, которая сразу становится неактивной, а активной становится стоп сервер. Все бы ничего до тех пор пока не нечинаю слушать сокет через while True, сразу окно блокируется. Может кто подскажет, каким образом это делается?

Прошу прощение, если слишком раскидано по файлам, мне как то удобнее так.

main.py
import sys
import argparse
import logging
from PyQt5.QtWidgets import QApplication

from ui import App
from db import Database
from ZMQ_server import ZServer

LOGGER = logging.getLogger(__name__)

db_name = 'proba.db'
app_args = []


def parse_arg(args):
    parser = argparse.ArgumentParser()
    parser.add_argument('-v', '--verbose',
                        action='count',
                        default=1,
                        help='Verbose level')
    return parser.parse_args(args)


def init_logger(level):
    logger = logging.getLogger()
    logger.addHandler(logging.StreamHandler())
    if level == 1:
        logger.setLevel(logging.INFO)
    elif level == 2:
        logger.setLevel(logging.DEBUG)
    else:
        logger.setLevel(logging.WARNING)


def main():
    try:
        options = parse_arg(sys.argv[1:])
        init_logger(options.verbose)
        LOGGER.info('Starting...')

        try:
            # Database
            database = Database(db_name)
            database.db_connect()
            database.db_tables_creation()
            LOGGER.info('DB connected')

            # Server
            server = ZServer()

            # Window
            app = QApplication(app_args)
            window = App(database, server)
            window.initUI()
            sys.exit(app.exec_())

        except Exception as err:
            LOGGER.warning('Error at init %s', err)

    except KeyboardInterrupt:
        sys.exit(0)

    except Exception as err:  # pylint: disable=broad-except
        LOGGER.exception(err)
        sys.exit(1)

    finally:
        try:
            database.db_disconnect()
            LOGGER.info('DB connection closed')
            server.stop()
            LOGGER.info('Server is stopped')
        except UnboundLocalError:
            pass
        LOGGER.info('Stopped correctly')

if __name__ == '__main__':
    main()


db.py кидывать не буду, там просто создание бд и таблиц

ZMQ_server.py
import asyncio
import zmq
import zmq.asyncio
import logging

ctx = zmq.asyncio.Context()
LOGGER = logging.getLogger(__name__)


class ZServer(object):

    def __init__(self):
        self.socket = None

    def start(self, protocol, host, port):
        address = protocol + '://' + host + ':' + port
        try:
            self.socket = ctx.socket(zmq.REP)
            self.socket.bind(address)
            if self.socket.closed is not True:
                LOGGER.info('Server ready at address %s', address)
                # loop = asyncio.get_event_loop() # скрыл это пока что чтоб не ждать ответа
                # loop.run_until_complete(self.run())
        except Exception as err:
            LOGGER.warning('Unable create server due to %s', err)

    def run(self):
        # while True:  # Так же пока скрыл
        #     msg = yield from self.socket.recv()
        #     if msg:
        #         LOGGER.info('MSG %s', msg.decode('ascii'))
        pass

    def stop(self):
        try:
            self.socket.close()
            if self.socket.closed is True:
                LOGGER.info('Server closed')
        except Exception as err:
            LOGGER.warning('Unable disconnect server due to %s', err)


Ну и сам PyQT ui.py, main_window просто набор виджетов и т.п. с дизайнера
from PyQt5.QtWidgets import QWidget, QMainWindow
from main_window import Ui_MainWindow


class App(object):

    def __init__(self, database, server):
        self.window = QMainWindow()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self.window)
        self.database = database
        self.server = server
        self.ui.serverStopButton.setDisabled(True)
        self.ui.serverStartButton.clicked.connect(self.start_server)
        self.ui.serverStopButton.clicked.connect(self.stop_server)

    def initUI(self):
        self.window.setWindowTitle('Nova FX advisor')
        self.window.show()

    def start_server(self):
        host_input = self.ui.serverHostInput.text()
        port_input = self.ui.serverPortInput.text()
        host = host_input if host_input else '127.0.0.1'
        port = port_input if port_input else '5599'
        self.server.start('tcp', host, port)
        self.ui.serverStartButton.setDisabled(True)
        self.ui.serverStopButton.setDisabled(False)

    def stop_server(self):
        self.server.stop()
        self.ui.serverStartButton.setDisabled(False)
        self.ui.serverStopButton.setDisabled(True)
  • Вопрос задан
  • 278 просмотров
Решения вопроса 1
@bbkmzzzz
Цикл событий Qt тоже должен как-то работать)
1 - выносить сервер в отдельный QThread
2 - Использовать Qt
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы