如何在python中使用QTextBrowser而不是控制台? [英] How to use a QTextBrowser instead of the console in python?

查看:221
本文介绍了如何在python中使用QTextBrowser而不是控制台?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 pyqt5 中构建了一个窗口,通过单击优化"按钮,程序读取Gurobi-model.lp"文件(点击获取文件),并借助Gurobi软件进行优化.如何在 QTextBrowser 上显示 Gurobi 的日志?

I've constructed a window in pyqt5, which by clicking on "optimize" button, the program reads the "Gurobi-model.lp" file(click here to get the file), and optimizes it by the help of the Gurobi software. How can I display the logs of the Gurobi on a QTextBrowser?

我在 Gurobi 中找到了一些函数,例如 OutputFlag、LogFile、LogToConsole.然而,我搜索了很多,我不明白这些功能对我有没有帮助.有人可以在这方面帮助我吗?

I found some functions in the Gurobi such as OutputFlag, LogFile, LogToConsole. However, I searched a lot, and I didn't understand these functions might be helpful for me or not. Anybody can help me in this regard?

对于不熟悉 Gurobi 的人,Gurobi 优化器使用 python 作为接口,并生成一些日志,可以让您跟踪优化进度.这些日志在优化过程中会打印在控制台中,不知何故,回答我的问题不需要了解有关 Gurobi 的任何信息.

For those who are not familiar with Gurobi, the Gurobi optimizer uses python as an interface, and produces some logs that allows you to track the progress of the optimization. These logs are printed in the console during the optimization, and somehow, responding my question doesn't need to know anything about the Gurobi.

在下面的代码中,我找到了一种在 QTextBrowser 中显示日志的方法,但是当优化过程完全完成时会显示日志.我希望在优化过程中准确表示日志.

In the below code, I've found a way to show the logs in the QTextBrowser, but the logs are represented when the optimization process is completely done. I want the logs to be represented exactly during the optimization process.

import sys 
from PyQt5.QtWidgets import *
from gurobipy import *
from io import *


class MyWindow(QWidget): 

    def __init__(self): 
        QWidget.__init__(self) 

        self.pb = QPushButton(self.tr("optimize"))
        self.log_text = QTextBrowser()

        layout = QVBoxLayout(self)
        layout.addWidget(self.pb)
        layout.addWidget(self.log_text)
        self.setLayout(layout)

        self.pb.clicked.connect(self.optimize)

     def optimize(self):

        f = StringIO()
        sys.stdout = StringIO()

        self.m = read('Gurobi-model.lp')
        self.m.optimize()
        self.log_text.append(sys.stdout.getvalue() )


def main(): 
   app = QApplication(sys.argv) 
   w = MyWindow() 
   w.show() 
   sys.exit(app.exec_())       

if __name__ == "__main__": 
    main()

推荐答案

优化任务很繁重,因此不应在 GUI 的同一线程中执行,也不应在同一进程中执行,为此您应该使用多处理模块,另一方面,如果您需要在 QTextBrowser 中显示控制台的输出,则必须使用通过信号传递它的日志记录模块(最后一部分使用 这篇文章的答案)

the task of optimizing is heavy so it should not be executed in the same thread of the GUI, nor in the same process, for this you should use the multiprocessing module, on the other hand if you need to show the output of the console in the QTextBrowser you must use the logging module passing it through signal, (for the last part use the answer of this post)

import sys
import logging
import multiprocessing
from logging.handlers import QueueHandler, QueueListener
from PyQt5 import QtCore, QtWidgets
from gurobipy import *

class LogEmitter(QtCore.QObject):
    sigLog = QtCore.pyqtSignal(str)

class LogHandler(logging.Handler):
    def __init__(self):
        super().__init__()
        self.emitter = LogEmitter()

    def emit(self, record):
        msg = self.format(record)
        self.emitter.sigLog.emit(msg)

def long_task():
    m = read('Gurobi-model.lp')
    m.optimize()

def worker_init(q):
    qh = QueueHandler(q)
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    logger.addHandler(qh)

class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(MyWindow, self).__init__(parent)

        self.pb = QtWidgets.QPushButton(self.tr("optimize"), 
            clicked=self.start_optimize)
        self.log_text = QtWidgets.QPlainTextEdit(readOnly=True)

        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.pb)
        layout.addWidget(self.log_text)

        self.running = False
        handler = LogHandler()
        handler.emitter.sigLog.connect(self.log_text.appendPlainText)

        self.q = multiprocessing.Queue()
        self.ql = QueueListener(self.q, handler)
        self.ql.start()

        self.main_log = logging.getLogger('main')
        self.main_log.propagate = False
        self.main_log.setLevel(logging.INFO)
        self.main_log.addHandler(QueueHandler(self.q))
        self.pool = multiprocessing.Pool(1, worker_init, [self.q])

    @QtCore.pyqtSlot()
    def start_optimize(self):
        if not self.running:
            self.pool.apply_async(long_task, callback=self.handle_result)

    def handle_result(self, result=None):
        self.running = False

    def closeEvent(self, event):
        self.ql.stop()
        super(MyWindow, self).closeEvent(event)

def main(): 
   app = QtWidgets.QApplication(sys.argv) 
   w = MyWindow() 
   w.show() 
   sys.exit(app.exec_())       

if __name__ == "__main__": 
    main()

这篇关于如何在python中使用QTextBrowser而不是控制台?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆