multiprocessing and GUI updating - Qprocess or multiprocessing?

后端 未结 2 1872
陌清茗
陌清茗 2020-12-15 01:36

After reading the literature on QProcesses and the multiprocessing module for python, I am still having trouble creating a working and responsive GUI throughout having large

2条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-15 02:11

    Even though the question is old and has been answered I would like add some clarification:

    • AFAIK QtConcurrent is not available in PyQt.
    • Threads in Qt with C++ are different from PyQt or python threads. The latter need to acquire python's GIL (global interpreter lock) when they run which effectively means that there is no real concurrency between python/pyqt threads.

    Python threads are ok to keep the gui responsive, but you won't see any performance improvements for cpu bound tasks. I recommend using multiprocessing together with a QThread on your main process that handles the communication with the child process. You can use signals and slots between your main (gui) and your communication thread.

    enter image description here

    edit: I just had the same problem and did something along these lines:

    from multiprocessing import Process, Queue
    from PyQt4 import QtCore
    from MyJob import job_function
    
    
    # Runner lives on the runner thread
    
    class Runner(QtCore.QObject):
        """
        Runs a job in a separate process and forwards messages from the job to the
        main thread through a pyqtSignal.
    
        """
    
        msg_from_job = QtCore.pyqtSignal(object)
    
        def __init__(self, start_signal):
            """
            :param start_signal: the pyqtSignal that starts the job
    
            """
            super(Runner, self).__init__()
            self.job_input = None
            start_signal.connect(self._run)
    
        def _run(self):
            queue = Queue()
            p = Process(target=job_function, args=(queue, self.job_input))
            p.start()
            while True:
                msg = queue.get()
                self.msg_from_job.emit(msg)
                if msg == 'done':
                    break
    
    
    # Things below live on the main thread
    
    def run_job(input):
        """ Call this to start a new job """
        runner.job_input = input
        runner_thread.start()
    
    
    def handle_msg(msg):
        print(msg)
        if msg == 'done':
            runner_thread.quit()
            runner_thread.wait()
    
    
    # Setup the OQ listener thread and move the OQ runner object to it
    runner_thread = QtCore.QThread()
    runner = Runner(start_signal=runner_thread.started)
    runner.msg_from_job.connect(handle_msg)
    runner.moveToThread(runner_thread)
    

提交回复
热议问题