【问题标题】:How can I use a QTextBrowser instead of the console in Python?如何在 Python 中使用 QTextBrowser 而不是控制台?
【发布时间】:2019-02-12 05:18:57
【问题描述】:

我在 PyQt 5 中构建了一个窗口,通过单击“优化”按钮,程序读取“Gurobi-model.lp”文件(click here to get the file),并借助 Gurobi 软件对其进行优化。如何在 QTextBrowser 上显示 Gurobi 的日志?

我在 Gurobi 中找到了一些函数,例如 OutputFlag、LogFile 和 LogToConsole。这些功能可能没有帮助吗?

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

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

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()

【问题讨论】:

    标签: python python-3.x pyqt5 gurobi


    【解决方案1】:

    优化任务繁重,不应该在GUI的同一个线程中执行,也不应该在同一个进程中执行。为此,您应该使用多处理模块。另一方面,如果您需要在 QTextBrowser 中显示控制台的输出,则必须使用 logging 模块,通过信号传递它(最后一部分,使用本文的the answer)。

    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()
    

    【讨论】:

      猜你喜欢
      • 2014-10-13
      • 2015-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多