티스토리 뷰

파이썬에서 stdout을 pyqt5 로 리다이렉션 하는 법을 설명 드리겠습니다. 크게 요약드리자면 sys.stdout.write를 textBrowser의 insertPlainText 메소드로 연결 시키는 방법입니다.


우선 아래 처럼 StdoutRedirect 클래스를 만들어 줍니다. 그리고 시그널을 생성해야 합니다.  아래코드는 start method 가 불리면 sys.stdout.write (또다른 말로는 print) 가 불릴 때 마다, printOccur 시그널을 emit하는 클래스 입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class StdoutRedirect(QObject):
    printOccur = pyqtSignal(strstr, name="print")
 
    def __init__(self, *param):
        QObject.__init__(self, None)
        self.daemon = True
        self.sysstdout = sys.stdout.write
        self.sysstderr = sys.stderr.write
 
    def stop(self):
        sys.stdout.write = self.sysstdout
        sys.stderr.write = self.sysstderr
 
    def start(self):
        sys.stdout.write = self.write
        sys.stderr.write = lambda msg : self.write(msg, color="red")
 
    def write(self, s, color="black"):
        sys.stdout.flush()
        self.printOccur.emit(s, color)
cs



그리고 위에서 선언된 StdoutRedirect() 를 생성 한 후, 아래 처럼 시그널을 연결 합니다.  line9 에서 실제로 slot을 connect 시키는 부분 입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 해당 코드는 copy paste로 사용이 바로 불가능 합니다. ui 파일을 첨부하지 않았습니다.
 
class ConsoleView(QWidget, form_class):
    def __init__(self, parent = None):
        super(ConsoleView, self).__init__(parent)
        self.setupUi(self)
        
        # member variable     
        self._stdout = StdoutRedirect()
        self._stdout.start()
        self._stdout.printOccur.connect(lambda x : self._append_text(x))
 
    def _append_text(self, msg):
        self.textBrowser.moveCursor(QtGui.QTextCursor.End)
        self.textBrowser.insertPlainText(msg)
        # refresh textedit show, refer) https://doc.qt.io/qt-5/qeventloop.html#ProcessEventsFlag-enum
        QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)
cs


해당 코드에서 가장 중요한 부분은 

line 17 에서 QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)

입니다.


저 부분을 해주지 않으면 print 가 호출 될 때 시간이 걸리는 작업들이 있으면 (time.sleep 등) 바로바로 화면으로 업데이트 해주지 않습니다. 모든 작업이 끝난 후에야 textBrowser 에 업데이트가 됩니다... 그래서 마치 프로그램이 멈춘것 처럼 보이죠. 영상2 처럼 멈췄다가 한번에 출력이 됩니다. 아래 영상의 프로그램은 pyqt5 로 구현한 것입니다. 



<영상1. processEvent를 적용했을 때 출력 부분>



<영상2. processEvent를 적용하지 않았을 때 출력>

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함