我有一个可行的体系结构,但仍有改进的空间。 我正在寻找有关改进此实现的建议。
我想消除Manager.Queue()和QThread()。这些似乎使人们无法通过多进程数据交换。
我的搜索使我陷入了这种疯狂- Async like pattern in pyqt? Or cleaner background call pattern? 有更容易的方法吗 ?
以下是演示我要改进的代码-
import multiprocessing
import queue
import sys
import time
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QLabel, QVBoxLayout
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QThread, pyqtSignal, pyqtSlot
def dataProducer(q):
cnt = 0
time.sleep(2)
while True:
print ("step 1 : producer %d" % cnt)
q.put({ 'cnt' : cnt })
cnt += 1
time.sleep(1)
class App(QMainWindow):
sig_msg = pyqtSignal(object) # this is the magic to send data to the gui
def __init__(self, q):
super().__init__()
self.title = 'plumbing'
self.left = 10
self.top = 10
self.width = 400
self.height = 140
self.q = q
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.consumerThread = QThread()
self.sig_msg.connect(self.handleData) # connect signal to handler
self.consumerThread.started.connect(self.dataConsumer) # connect QThread to slot
self.consumerThread.start()
self.show()
def handleData(self, data):
print ("step 3 : handler %s" % str(data))
@pyqtSlot()
def dataConsumer(self):
while True:
try:
data = self.q.get_nowait()
except queue.Empty:
time.sleep(0.001)
continue
print ("step 2 : consumer %s" % str(data))
self.sig_msg.emit(data)
if __name__ == '__main__':
q = multiprocessing.Queue()
p = multiprocessing.Process(target=dataProducer, args=(q,))
p.start()
app = QApplication(sys.argv)
ex = App(q)
sys.exit(app.exec_())
输出为-
step 1 : producer 0
step 2 : consumer {'cnt': 0}
step 3 : handler {'cnt': 0}
step 1 : producer 1
step 2 : consumer {'cnt': 1}
step 3 : handler {'cnt': 1}
step 1 : producer 2
step 2 : consumer {'cnt': 2}
step 3 : handler {'cnt': 2}
step 1 : producer 3
step 2 : consumer {'cnt': 3}
step 3 : handler {'cnt': 3}
step 1 : producer 4
step 2 : consumer {'cnt': 4}
step 3 : handler {'cnt': 4}
我能达到的最接近的方法是将信号传递给我的Process(),但是这要求我更改一个第三方库,而该库必须不断修补更新。
import multiprocessing
import queue
import sys
import time
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QLabel, QVBoxLayout
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QThread, pyqtSignal, pyqtSlot
def dataProducer(ex):
cnt = 0
time.sleep(2)
while True:
print ("step 1 : producer %d" % cnt)
ex.sig_msg.emit({ 'cnt' : cnt })
cnt += 1
time.sleep(1)
class App(QMainWindow):
sig_msg = pyqtSignal(object) # this is the magic to send data to the gui
def __init__(self):
super().__init__()
self.title = 'plumbing'
self.left = 10
self.top = 10
self.width = 400
self.height = 140
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.sig_msg.connect(self.handleData) # connect signal to handler
self.show()
def handleData(self, data):
print ("step 3 : handler %s" % str(data))
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
p = multiprocessing.Process(target=dataProducer, args=(ex,))
p.start()
sys.exit(app.exec_())