最近一个项目中想要使用pyqtSignal实时在窗口中append另外一个进程中接收到的信号,但是试了好几次,都无法接收到emit信号,并且用id(signal)发现所有signal实例都是同一个。这就很奇怪了。
搜索后发现,原来是因为pyqt的signal只能够在同一个进程的不同线程中进行传递,而跨进程就不行,需要用到进程间通信,如队列,才能解决。
参考:https://www.v2ex.com/t/346882
没办法,只能暂时放弃这个想法了,毕竟对进程间通信还是很陌生
2020-03-02更新
经过几天的摸索,已经能够使用mutiprocessing.Queue进行进程间消息队列
from PyQt5.QtCore import QThread, pyqtSignal
from module.ui import *
import multiprocessing
class readThread(QThread):
def __init__(self, q, sig):
super(readThread, self).__init__()
self.q = q
self.sig = sig
def run(self):
while True:
if not self.q.empty():
value = self.q.get(True)
self.sig.emit(value)
self.sleep(1)
class MyForm(QtWidgets.QMainWindow):
sig = pyqtSignal(dict)
def __init__(self):
super().__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.startSyncButton.clicked.connect(self.start_sync)
self.sig.connect(self.display_log)
self.q = multiprocessing.Queue()
self.read_thread = readThread(self.q, self.sig)
def start_sync(self):
# 为flask开启进程
self.process = syncClass(self.q)
self.process.start()
# 为log显示开启线程
self.read_thread.start()
def display_log(self, log):
# 添加tableWidget中展示数据
numRows = self.ui.tableWidget.rowCount()
self.ui.tableWidget.insertRow(numRows)
for key, value in log.items():
column_name = self.translate[key]
column_num = self.num[column_name]
self.ui.tableWidget.setItem(numRows, int(column_num), QTableWidgetItem(str(value)))
class syncClass(multiprocessing.Process):
def __init__(self, q):
multiprocessing.Process.__init__(self)
self.exit = multiprocessing.Event()
self.q = q
def run(self):
simple_page = server.construct_blueprint(self.q)
app = Flask(__name__)
app.register_blueprint(simple_page)
app.run(host="0.0.0.0",port=3100)
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(True)
w = MyForm()
app.setWindowIcon(QIcon("icon/logo.png"))
app.aboutToQuit.connect(w.close_connection)
# 设置最大显示
w.showMaximized()
w.show()
sys.exit(app.exec_())
上面的代码只是一个简单的框架,并不能执行,其实现的流程为:
- 初始化界面、生成sig信号实例、生成q队列实例、生成read_thread读线程实例并传入q和sig;
- 点击startSyncButton,进入start_sync函数中,并传入q队列实例;
- start_sync函数实现:
- 实例化process并start process进程,该进程实现监听端口,如果有请求传入,就向队列q中put解析后的消息;
- start read_thread线程,该线程实现周期循环读队列q,如果有新消息,就emit信号;
- sig收到信号后连接槽函数display_log,该函数实现将消息输出到tableWidget中。