PyQt5 从主模块外部实时登录 QTextedit
Posted
技术标签:
【中文标题】PyQt5 从主模块外部实时登录 QTextedit【英文标题】:PyQt5 realtime logging in QTextedit from outside main module 【发布时间】:2020-12-26 12:19:09 【问题描述】:我花了很长时间才在这里发布我的第一个问题,因为我过去所有问题的所有答案都已经在这里了。但是我还没有找到解决这个问题的方法,所以我们开始吧:
描述:在我的应用程序中,我想在 QTextEdit 小部件中显示实时日志记录信息。为了让它工作,我实现了我找到的解决方案here。
问题:只要所有执行的函数都是主 Window 类的一部分,上面链接中的代码就像一个魅力。但是对于我的应用程序,我需要它在主模块之外工作。我希望能够从外部函数获取实时日志信息(每行一行)(例如:当“someProcess”函数位于另一个模块中时,请参见下面的代码)。当我尝试这样做时,一切正常,但它不像以前那样显示每行的日志信息行,而是在外部函数完成后一次显示所有行。
我认为这是合乎逻辑的,因为在外部函数中,外部模块中的记录器对象没有发出信号。但我想不出一个简单(或任何)的方法来实现这一点。
main.py
import sys
import time
import logging
import othermodule as om
from PyQt5.QtCore import QObject, pyqtSignal, QThread
from PyQt5.QtWidgets import QWidget, QTextEdit, QPushButton, QVBoxLayout, QApplication
logger = logging.getLogger(__name__)
class ConsoleWindowLogHandler(logging.Handler, QObject):
sigLog = pyqtSignal(str)
def __init__(self):
logging.Handler.__init__(self)
QObject.__init__(self)
def emit(self, logRecord):
message = str(logRecord.getMessage())
self.sigLog.emit(message)
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
# Layout
textBox = QTextEdit()
textBox.setReadOnly(True)
self.button = QPushButton('Click')
vertLayout = QVBoxLayout()
vertLayout.addWidget(textBox)
vertLayout.addWidget(self.button)
self.setLayout(vertLayout)
# Connect button
self.button.clicked.connect(self.buttonPressed)
# Thread
self.bee = Worker(self.test, ())
self.bee.finished.connect(self.restoreUi)
self.bee.terminate()
# Console handler
consoleHandler = ConsoleWindowLogHandler()
consoleHandler.sigLog.connect(textBox.append)
logger.addHandler(consoleHandler)
def buttonPressed(self):
self.button.setEnabled(False)
self.bee.start()
def restoreUi(self):
self.button.setEnabled(True)
def test(self):
logger.error('Starting')
om.someProcess()
class Worker(QThread):
def __init__(self, func, args):
super(Worker, self).__init__()
self.func = func
self.args = args
def run(self):
self.func(*self.args)
def main():
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
其他模块.py
import time
import logging
logger = logging.getLogger(__name__)
def someProcess(self):
logger.error("starting")
for i in range(10):
logger.error("line%d" % i) # Every iteration, I want to display this line per line
# in the textbox on the main window
time.sleep(2) # in my own code, here comes a time consuming task
【问题讨论】:
【参考方案1】:这个错误是因为ConsoleWindowLogHandler只处理main.py中创建的logger的信息,而不是othermodule.py中创建的logger的信息,解决方法是指定ConsoleWindowLogHandler也是othermodule.py中创建的logger的handler :
# Console handler
consoleHandler = ConsoleWindowLogHandler()
consoleHandler.sigLog.connect(textBox.append)
logger.addHandler(consoleHandler)
om.logger.addHandler(consoleHandler)
注意:虽然这很简单,但您应该将def someProcess(self):
更改为def someProcess():
【讨论】:
以上是关于PyQt5 从主模块外部实时登录 QTextedit的主要内容,如果未能解决你的问题,请参考以下文章
[ PyQt入门教程 ] PyQt5中多线程模块QThread使用方法
使用 Celery 通过 Gevent 进行实时、同步的外部 API 查询
如何将变量从 PyQt5 UI 返回到 Main 函数 - Python
PyQt5中多线程模块QThread解决界面卡顿无响应问题,线程池ThreadPoolExecutor解决多任务耗时操作问题
PyQt5中多线程模块QThread解决界面卡顿无响应问题,线程池ThreadPoolExecutor解决多任务耗时操作问题