PyQt MainWindow在Windows上使用多处理

时间:2017-01-12 21:43:01

标签: pyqt multiprocessing python-3.6

我尝试创建一个PyQt应用程序。为了在后台运行进程并使PyQt5应用程序可用于新指令,我想使用multiprocessing。 在Windows操作系统上,当我使用MainWindow从Qt multiprocessing.process类调用一个函数时,我有一个关于pickle这个类的错误。但它正在Linux上运行find。

以下是一个例子:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys          
import multiprocessing

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


class Frame_main(QMainWindow):

    def __init__(self, parent = None):
        super(Frame_main, self).__init__(parent)
        self.thrd_list=[]
        self.initUI()

    def initUI(self):

        # Button 
        btn_run = QPushButton('Run', self)      
        btn_run.clicked.connect(lambda: self.ThdSomething(self.DoRun) ) #
        btn_stop = QPushButton('Stop', self)     
        btn_stop.clicked.connect(self.DoStop)    


        ### TEXT Edit       
        self.textEdit_term = QTextEdit("terminal: \n ")
        self.textEdit_term.append("")
        self.textEdit_term.setStyleSheet("color: rgb(255, 255, 255); background-color: black;")
        self.textEdit_term.setLineWrapMode(QTextEdit.NoWrap)
        self.textEdit_term.setToolTip(' terminal message ')
        self.textEdit_term.setStatusTip('textEdit1')

        ### LAYOUT
        Wid_main = QWidget()                    # 
        grid_major = QGridLayout()              # 
        grid_major.addWidget( btn_run, 1, 5)
        grid_major.addWidget( btn_stop, 2, 5)
        Wid_main.setLayout(grid_major)

        self.setCentralWidget(Wid_main)

        ### Affichage 
        self.show()                 #

    # 
    def DoRun(self):
        print('g starts')
        time_start=time.time()
        time_stop=time.time()
        name='bob'
        n=0
        while time_stop-time_start <2 :
            n+=1
            time_stop=time.time()
            time.sleep(0.8)
            print ('hola', name,n, flush=True)
        print('g stops')

    def DoStop(self):
        ''' subourtine kill all the thread '''
        print('stop action detected')
        while len(self.thrd_list) > 0 :
            print("Terminating the job: {}".format(self.thrd[-1].pid) )
            os.kill(self.thrd[-1].pid, signal.SIGTERM) 
            self.thrd_list[-1].terminate()

            self.thrd_list.pop()


    def ThdSomething(self, job):
        ''' subourtine to create a new thread to do the job subroutine '''
        arg=''
        p=multiprocessing.Process(target=job, args=(arg))
        self.thrd_list.append( p )
        p.start()
        print("Start the job GUI: {} with PID: {}".format(str(job) ,self.thrd[-1].pid), file=sys.stdout )


    def closeEvent(self, event):
        ''' subroutine to define what happen when closing the main frame'''
        self.statusBar().showMessage('waiting for a respond') 
        reply = QMessageBox.question(self, 'Message',
            "Are you sure to quit?", QMessageBox.Yes | 
            QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()


# Main
if __name__ == '__main__':  
    # Create QApplication and Main Frame
    Qapp = QApplication(sys.argv)   # creation de lappli Qt
    Qapp.setStyle("fusion")         # 
    frame1 = Frame_main()           # 

    sys.exit(Qapp.exec_())          #

编辑:

我发现了几个类似的案例,如: Python: multiprocessing in pyqt application 但他们都没有帮助。我认为这可能与我的案例使用MainWindow类的函数和属性这一事实有关。

1 个答案:

答案 0 :(得分:2)

这是正确的,这是因为尝试在GUI类中分叉方法。不幸的是,Windows并没有像linux那样实现fork进程的能力,这就是为什么你的代码在linux而不是在windows上工作的原因。 Python 3 documentation for the multiprocessing library提供了一些有关差异的有用信息,以及启动新流程的默认方法在不同平台下的用途。

回答你的问题:因为你的目标是一个与GUI对象相关联的方法,它必须将对象状态发送到新进程但却无法剔除它,因为PyQt GUI对象太复杂而无法腌制。

如果您重写代码以便可以选择目标函数(以及指定的args),那么您的代码将起作用。