PyQt应用执行Discord RPC更新函数时无响应崩溃求助
解决思路与代码修复
问题核心原因
你当前的代码里,onclick函数用了while True+time.sleep(100),直接把Qt的主线程卡死了——Qt的UI事件循环完全没法运行,自然会无响应。哪怕改成单次调用,RPC.update本身的同步阻塞操作也会短暂卡住主线程。另外,你在模块最外层直接调用RPC.connect(),这个连接操作在主线程执行,一旦Discord响应慢,也会拖垮UI。
具体修复方案
方案1:用QTimer定时更新(最简单,适配你的场景)
用Qt自带的QTimer代替死循环和sleep,定时触发RPC更新,完全不阻塞主线程:
from pypresence import Presence import time from PyQt5 import QtCore, QtGui, QtWidgets client_id = "997609359427260416" class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(485, 425) MainWindow.setStyleSheet("background-color: #1f1f1f;""font: 75 8pt \"Arial\";") self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.pushButton = QtWidgets.QPushButton(self.centralwidget, clicked = lambda: self.onclick()) self.pushButton.setGeometry(QtCore.QRect(160, 350, 161, 51)) self.pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.pushButton.setAutoFillBackground(False) self.pushButton.setStyleSheet("background-color: #a30b00;""color: white;""transition: 0.25s;""font: 12pt;""border-radius: 8px;""") self.pushButton.setObjectName("pushButton") self.label = QtWidgets.QLabel(self.centralwidget) self.label.setGeometry(QtCore.QRect(120, 10, 251, 31)) self.label.setStyleSheet("color: white;""font: 18pt") self.label.setObjectName("label") self.label_2 = QtWidgets.QLabel(self.centralwidget) self.label_2.setGeometry(QtCore.QRect(210, 40, 91, 16)) self.label_2.setStyleSheet("color: #a30b00;""font: 12pt") self.label_2.setObjectName("label_2") self.lineEdit = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit.setGeometry(QtCore.QRect(80, 100, 321, 31)) self.lineEdit.setStyleSheet("background-color: rgb(44, 44, 44);""border: 2px solid rgb(60, 60, 60);""border-radius: 5px;""color: white;") self.lineEdit.setObjectName("lineEdit") self.label_3 = QtWidgets.QLabel(self.centralwidget) self.label_3.setGeometry(QtCore.QRect(80, 80, 121, 16)) self.label_3.setStyleSheet("color: white;""font-size: 12pt") self.label_3.setObjectName("label_3") self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_2.setGeometry(QtCore.QRect(80, 170, 321, 31)) self.lineEdit_2.setStyleSheet("background-color: rgb(44, 44, 44);""border: 2px solid rgb(60, 60, 60);""border-radius: 5px;""color: white;") self.lineEdit_2.setObjectName("lineEdit_2") self.label_4 = QtWidgets.QLabel(self.centralwidget) self.label_4.setGeometry(QtCore.QRect(80, 150, 121, 16)) self.label_4.setStyleSheet("color: white;""font-size: 12pt") self.label_4.setObjectName("label_4") self.lineEdit_3 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_3.setGeometry(QtCore.QRect(80, 230, 321, 31)) self.lineEdit_3.setStyleSheet("background-color: rgb(44, 44, 44);""border: 2px solid rgb(60, 60, 60);""border-radius: 5px;""color: white;") self.lineEdit_3.setObjectName("lineEdit_3") self.label_5 = QtWidgets.QLabel(self.centralwidget) self.label_5.setGeometry(QtCore.QRect(80, 210, 121, 16)) self.label_5.setStyleSheet("color: white;""font-size: 12pt") self.label_5.setObjectName("label_5") self.lineEdit_4 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_4.setGeometry(QtCore.QRect(80, 290, 321, 31)) self.lineEdit_4.setStyleSheet("background-color: rgb(44, 44, 44);""border: 2px solid rgb(60, 60, 60);""border-radius: 5px;""color: white;") self.lineEdit_4.setObjectName("lineEdit_4") self.label_6 = QtWidgets.QLabel(self.centralwidget) self.label_6.setGeometry(QtCore.QRect(80, 270, 121, 16)) self.label_6.setStyleSheet("color: white;""font-size: 12pt") self.label_6.setObjectName("label_6") MainWindow.setCentralWidget(self.centralwidget) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) # 新增定时器相关初始化 self.rpc_timer = QtCore.QTimer() self.rpc_timer.timeout.connect(self.update_rpc) self.rpc = None self.start_time = int(time.time()) def onclick(self): # 点击按钮时初始化RPC连接 if not self.rpc: self.rpc = Presence(client_id) self.rpc.connect() # 启动定时器,每100秒更新一次(单位是毫秒) self.rpc_timer.start(100 * 1000) # 先手动更新一次 self.update_rpc() def update_rpc(self): value1 = self.lineEdit.text() if self.rpc: self.rpc.update( large_image = "large", large_text = "test", details = value1, state = "Presence Changer", start = self.start_time, buttons = [{"label": "kndxiu on TikTok", "url": "https://tiktok.com/@kndxiu"}, {"label": "Website", "url": "https://kndxiu.xyz"}] ) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.pushButton.setText(_translate("MainWindow", "SAVE")) self.label.setText(_translate("MainWindow", "Discord RP Changer")) self.label_2.setText(_translate("MainWindow", "by kndxiu.")) self.label_3.setText(_translate("MainWindow", "test")) self.label_4.setText(_translate("MainWindow", "test")) self.label_5.setText(_translate("MainWindow", "test")) self.label_6.setText(_translate("MainWindow", "test")) if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_())
方案2:用QThread子线程处理RPC逻辑(适合复杂异步场景)
如果RPC操作存在长时间阻塞风险,把整个RPC逻辑放到子线程,彻底隔离主线程:
from pypresence import Presence import time from PyQt5 import QtCore, QtGui, QtWidgets client_id = "997609359427260416" class RPCWorker(QtCore.QThread): def __init__(self): super().__init__() self.rpc = None self.start_time = int(time.time()) self.details = "" self.running = False def run(self): self.rpc = Presence(client_id) self.rpc.connect() self.running = True while self.running: self.rpc.update( large_image = "large", large_text = "test", details = self.details, state = "Presence Changer", start = self.start_time, buttons = [{"label": "kndxiu on TikTok", "url": "https://tiktok.com/@kndxiu"}, {"label": "Website", "url": "https://kndxiu.xyz"}] ) time.sleep(100) def stop(self): self.running = False self.wait() if self.rpc: self.rpc.close() class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(485, 425) MainWindow.setStyleSheet("background-color: #1f1f1f;""font: 75 8pt \"Arial\";") self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.pushButton = QtWidgets.QPushButton(self.centralwidget, clicked = lambda: self.onclick()) self.pushButton.setGeometry(QtCore.QRect(160, 350, 161, 51)) self.pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.pushButton.setAutoFillBackground(False) self.pushButton.setStyleSheet("background-color: #a30b00;""color: white;""transition: 0.25s;""font: 12pt;""border-radius: 8px;""") self.pushButton.setObjectName("pushButton") self.label = QtWidgets.QLabel(self.centralwidget) self.label.setGeometry(QtCore.QRect(120, 10, 251, 31)) self.label.setStyleSheet("color: white;""font: 18pt") self.label.setObjectName("label") self.label_2 = QtWidgets.QLabel(self.centralwidget) self.label_2.setGeometry(QtCore.QRect(210, 40, 91, 16)) self.label_2.setStyleSheet("color: #a30b00;""font: 12pt") self.label_2.setObjectName("label_2") self.lineEdit = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit.setGeometry(QtCore.QRect(80, 100, 321, 31)) self.lineEdit.setStyleSheet("background-color: rgb(44, 44, 44);""border: 2px solid rgb(60, 60, 60);""border-radius: 5px;""color: white;") self.lineEdit.setObjectName("lineEdit") self.label_3 = QtWidgets.QLabel(self.centralwidget) self.label_3.setGeometry(QtCore.QRect(80, 80, 121, 16)) self.label_3.setStyleSheet("color: white;""font-size: 12pt") self.label_3.setObjectName("label_3") self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_2.setGeometry(QtCore.QRect(80, 170, 321, 31)) self.lineEdit_2.setStyleSheet("background-color: rgb(44, 44, 44);""border: 2px solid rgb(60, 60, 60);""border-radius: 5px;""color: white;") self.lineEdit_2.setObjectName("lineEdit_2") self.label_4 = QtWidgets.QLabel(self.centralwidget) self.label_4.setGeometry(QtCore.QRect(80, 150, 121, 16)) self.label_4.setStyleSheet("color: white;""font-size: 12pt") self.label_4.setObjectName("label_4") self.lineEdit_3 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_3.setGeometry(QtCore.QRect(80, 230, 321, 31)) self.lineEdit_3.setStyleSheet("background-color: rgb(44, 44, 44);""border: 2px solid rgb(60, 60, 60);""border-radius: 5px;""color: white;") self.lineEdit_3.setObjectName("lineEdit_3") self.label_5 = QtWidgets.QLabel(self.centralwidget) self.label_5.setGeometry(QtCore.QRect(80, 210, 121, 16)) self.label_5.setStyleSheet("color: white;""font-size: 12pt") self.label_5.setObjectName("label_5") self.lineEdit_4 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_4.setGeometry(QtCore.QRect(80, 290, 321, 31)) self.lineEdit_4.setStyleSheet("background-color: rgb(44, 44, 44);""border: 2px solid rgb(60, 60, 60);""border-radius: 5px;""color: white;") self.lineEdit_4.setObjectName("lineEdit_4") self.label_6 = QtWidgets.QLabel(self.centralwidget) self.label_6.setGeometry(QtCore.QRect(80, 270, 121, 16)) self.label_6.setStyleSheet("color: white;""font-size: 12pt") self.label_6.setObjectName("label_6") MainWindow.setCentralWidget(self.centralwidget) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) # 初始化子线程 self.rpc_worker = RPCWorker() def onclick(self): # 传递输入框的值给子线程 self.rpc_worker.details = self.lineEdit.text() if not self.rpc_worker.isRunning(): self.rpc_worker.start() # 窗口关闭时停止线程 def closeEvent(self, event): self.rpc_worker.stop() event.accept() def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.pushButton.setText(_translate("MainWindow", "SAVE")) self.label.setText(_translate("MainWindow", "Discord RP Changer")) self.label_2.setText(_translate("MainWindow", "by kndxiu.")) self.label_3.setText(_translate("MainWindow", "test")) self.label_4.setText(_translate("MainWindow", "test")) self.label_5.setText(_translate("MainWindow", "test")) self.label_6.setText(_translate("MainWindow", "test")) if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_())
额外注意事项
- 绝对不要在主线程执行任何阻塞操作(比如
time.sleep、网络请求),Qt的UI完全依赖主线程的事件循环维持响应 - 建议给
RPC.connect()和RPC.update()加上try-except捕获异常,避免Discord未启动或连接失败时直接崩溃 - 子线程里禁止直接操作UI元素,必须通过信号槽传递数据,这是Qt的硬性规则
内容的提问来源于stack exchange,提问作者kondziu
相关产品推荐
相关产品推荐

