Search code examples
pythonpyqt5multiprocessing

Start a process on click


I am trying to add multiprocessing to my project. To exemplify, I made a little project with just a button, and when the button is pressed, I want to start a process with a method, but the method is never called. How could I call the method within a process?

Here is my code:

from multiprocessing import Process

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys


class Window(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Python ")
        self.setGeometry(100, 100, 600, 400)
        self.UiComponents()
        self.show()

    def UiComponents(self):
        button = QPushButton("CLICK", self)
        button.setGeometry(200, 150, 100, 30)

        proc = Process(target=self.button_clicked)
        procs = []
        procs.append(proc)

        button.clicked.connect(proc.start)

    def button_clicked(self):
        print("pressed")


App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())

Solution

  • generally mixing both Qt GUI objects and anything that allows threading/multiprocessesing is not safe, and will either not work or cause a segmentation fault.

    the correct way to do it without crashing your application is to move the target function to be a function that doesn't relate to QT GUI. (not a member of any Qt GUI object or has a reference to any Qt GUI object)

    also processes can only start once, so you need to create one on every button press as follows:

    from multiprocessing import Process
    
    from PyQt5.QtWidgets import *
    from PyQt5.QtGui import *
    from PyQt5.QtCore import *
    import sys
    
    def some_function():
        print("hello")
    
    class Window(QMainWindow):
        def __init__(self):
            super().__init__()
    
            self.setWindowTitle("Python ")
            self.setGeometry(100, 100, 600, 400)
            self.UiComponents()
            self.show()
    
        def UiComponents(self):
            button = QPushButton("CLICK", self)
            button.setGeometry(200, 150, 100, 30)
    
            self.procs = []
    
            button.clicked.connect(self.button_clicked)
    
        def button_clicked(self):
            proc = Process(target=some_function)
            self.procs.append(proc)
            proc.start()
            
            
    if __name__ == "__main__":  # for windows compatibility
        App = QApplication(sys.argv)
        window = Window()
        sys.exit(App.exec())
    

    the button is connected to a function which belongs to a Qt object, but the process is connected to a function that is not in any way connected to Qt, and will therefore not crash your application.