pyqtSignal и python Соответствие многопроцессорности - PullRequest
0 голосов
/ 20 марта 2020

Привет стек переполнение Python Hive Mind,

Я создал комплекс PyQt5 UI, который имеет несколько потоков, которые взаимодействуют с небольшим количеством аппаратного обеспечения. Обилие большого количества данных (в конечном счете, с некоторой графикой в ​​пользовательском интерфейсе) и некоторая синхронизация между потоками с использованием q's, Pipes, Events и pyqtsignals. Все хорошо, все хорошо, luvly. Есть желание удалить QThread и перейти на многопроцессорность, чтобы пользовательский интерфейс можно было отключить. Все на самом деле вполне разумно и сделано за исключением незначительной проблемы pyqtsignal.

Многопроцессорная Процесс (ранее QThread) выполняет from PyQt5.QtCore import pyqtSignal и в какая-то точка будет излучать сигнал. Если сигнал передается процессу через __init__, код выполняет __init__, но в момент запуска процесса он падает с этой ошибкой:

" TypeError: PyQt5.QtCore.pyqtBoundSignal"object" не может выбрать "." но преимущество сигнала заключается в асинхронной природе и простоте connect для службы f(). Это также работает как в пользовательском, так и в не-пользовательском интерфейсе без проблем.

Интересно, если вы запустите пример Process с run() вместо start() он работает (см. Пример), но я знаю по горькому опыту, что это отрицательно влияет на синхронизацию процессов, что вызвало у меня стресс отладки на несколько недель.

Боюсь, что мне не хватает очевидный трюк - можете ли вы избавить меня от моих страданий?!?

фрагмент кода предполагает [MainWindow с pushbuttons для выхода (pb_exit) и on_start (pb_start)

python v3.8 и PyQt5 v5.13.2 Windows 10] * 105 1 *

    from PyQt5.QtCore import pyqtSignal
    from multiprocessing import Process

    class CTest(Process):
            def __init__(self, signal):
                name = 'Process'
                super().__init__(name=name)
                self.signal = signal
            # End of __init__

            def run(self):
                time.sleep(5)
                self.signal.emit(99)
            # End of run

class MainWindow(QMainWindow, Ui_FQPositioner):
    # signal to be passed to QThread but now to Process
    signal = pyqtSignal(int)

    def __init__(self, app):
        super(MainWindow, self).__init__()
        self.setupUi(self)

        self.pb_exit.clicked.connect(self.closeEvent)
        self.pb_start.clicked.connect(self.on_start)
        self.signal.connect(self.on_position)
        self.test = CTest(self.signal)
        self.show()
    # end of __init__

    def on_start(self):
        # start the service processes
        self.test.start()
        # self.test.run()
    # end of on_position

    def on_position(self,sig):
        disp_text = 'signal ({})'.format(sig)
        print(disp_text)
    # end of on_position

    def closeEvent(self, event):
        QApplication.quit()
    # End of closeEvent

def main():
    # run the app
    app = QApplication([])  # A new instance of QApplication
    fqApp = MainWindow(app)
    fqApp.show()                # Show the form
    app.exec_()                 # and execute the app

if __name__ == '__main__':
    sys.exit(main())
...