在Windows上使用多重处理的PyQt MainWindow [英] PyQt MainWindow using multiprocessing on Windows

查看:273
本文介绍了在Windows上使用多重处理的PyQt MainWindow的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I try to create a PyQt application. In order to run process in background and keep the PyQt5 application available for new instruction, I want to use multiprocessing. On the Windows OS, when I call a function from the Qt MainWindow class with multiprocessing.process, I have an error about pickling this class. But it is running find on Linux.

这里是一个例子:

#!/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:pyqt应用程序中的多处理 但他们都没有帮助.我认为这可能与我的案例正在使用MainWindow类的函数和属性有关.

I found several similar case, like : Python: multiprocessing in pyqt application but none of them helped. I think this might be linked to fact that my case is using function and attributes of the MainWindow class.

推荐答案

您是正确的,这是由于尝试在GUI类中分叉某个方法所致.不幸的是,Windows确实没有像Linux一样分叉处理的能力,这就是为什么您的代码在Linux而不是Windows上可以工作的原因. 用于多处理库的Python 3文档有关这些差异以及在不同平台下启动新进程的默认方法有哪些有用的信息.

You are correct that this is due to the attempt to fork on a method within the GUI class. Unfortunately windows doesn't really have the ability to fork processes the way linux does, which is why your code works on linux and not on windows. The Python 3 documentation for the multiprocessing library has some useful information on the differences and what the default method for starting a new process is under different platforms.

要回答您的问题:因为目标是与GUI对象关联的方法,它必须将对象状态发送到新进程,但由于PyQt GUI对象太复杂而无法腌制,因此无法使它腌制.

To answer your question: because your target is a method associated with a GUI object, it has to send the object state to the new process but fails to pickle it because a PyQt GUI object is far too complex to pickle.

如果您重写代码以使目标函数(和指定的args)可腌制,则代码将起作用.

If you rewrite your code so that the target function (and args specified) are picklable, your code will work.

这篇关于在Windows上使用多重处理的PyQt MainWindow的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆