Redirecting Output in PyQt

后端 未结 1 1342
-上瘾入骨i
-上瘾入骨i 2020-12-10 09:56

I have a QApplication, with a lot of classes and functions, which displays a lot of stdout on the console. I want to redirect this stdout and stderr to a QTextBrowser(this i

相关标签:
1条回答
  • 2020-12-10 10:46

    I have made a library of open-source PyQt custom widgets - one of which is a logger class (XLoggerWidget) and another of which is a full Python interpreter (XConsoleEdit). It does what you're looking for.

    You can get it here if you want: http://dev.projexsoftware.com/projects/projexui

    The part you're looking for is in the XConsoleEdit (projexui.widgets.xconsoleedit), but the general gist of it is:

    import logging
    import sys
    
    from PyQt4.QtCore import QObject,\
                             pyqtSignal
    
    from PyQt4.QtGui import QDialog, \
                            QVBoxLayout, \
                            QPushButton, \
                            QTextBrowser,\
                            QApplication
    
    logger = logging.getLogger(__name__)
    
    class XStream(QObject):
        _stdout = None
        _stderr = None
    
        messageWritten = pyqtSignal(str)
    
        def flush( self ):
            pass
    
        def fileno( self ):
            return -1
    
        def write( self, msg ):
            if ( not self.signalsBlocked() ):
                self.messageWritten.emit(unicode(msg))
    
        @staticmethod
        def stdout():
            if ( not XStream._stdout ):
                XStream._stdout = XStream()
                sys.stdout = XStream._stdout
            return XStream._stdout
    
        @staticmethod
        def stderr():
            if ( not XStream._stderr ):
                XStream._stderr = XStream()
                sys.stderr = XStream._stderr
            return XStream._stderr
    
    class MyDialog(QDialog):
        def __init__( self, parent = None ):
            super(MyDialog, self).__init__(parent)
    
            # setup the ui
            self._console = QTextBrowser(self)
            self._button  = QPushButton(self)
            self._button.setText('Test Me')
    
            # create the layout
            layout = QVBoxLayout()
            layout.addWidget(self._console)
            layout.addWidget(self._button)
            self.setLayout(layout)
    
            # create connections
            XStream.stdout().messageWritten.connect( self._console.insertPlainText )
            XStream.stderr().messageWritten.connect( self._console.insertPlainText )
    
            self._button.clicked.connect(self.test)
    
        def test( self ):
            # print some stuff
            print 'testing'
            print 'testing2'
    
            # log some stuff
            logger.debug('Testing debug')
            logger.info('Testing info')
            logger.warning('Testing warning')
            logger.error('Testing error')
    
            # error out something
            print blah
    
    if ( __name__ == '__main__' ):
        logging.basicConfig()
    
        app = None
        if ( not QApplication.instance() ):
            app = QApplication([])
    
        dlg = MyDialog()
        dlg.show()
    
        if ( app ):
            app.exec_()
    

    This is a simplified version of whats in the XConsoleEdit, but its the general idea and should still work for what you're going for if you don't want to download the code.

    In this example tho, you'll notice that only the print and error logs are routed through to the edit. If you want to connect the Python logging system to the edit, you'll need something a little more complex where you define a logging.Handler and link it to your widget.

    That code would be found in projexui.widgets.xloggerwidget

    Its a bit longer and more complex, so I'm not going to load it up here...but if you have any questions about it, let me know.

    0 讨论(0)
提交回复
热议问题