在Windows上使用多重处理的PyQt MainWindow [英] PyQt MainWindow using multiprocessing on Windows
问题描述
我尝试创建一个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屋!