在QPlainTextEdit中使用tqdm显示终端输出 [英] Display terminal output with tqdm in QPlainTextEdit

查看:685
本文介绍了在QPlainTextEdit中使用tqdm显示终端输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找到一种方法,与其他打印件一起,在pyqt应用程序中(例如在QPlainTextEdit小部件中)获得进度条的结果/演变.

I'm trying to find a way of getting, along with other prints, the result/evolution of a progress bar in a pyqt application, for example in a QPlainTextEdit widget.

我面临的问题是,进度条可以使用一些更高级的回车键,甚至可以使用更高级的光标定位功能,而多数情况下,这些定位键都不支持. 我已经尝试过io.StringIO,但是\r保持原义.

The problem I'm facing, is that progress bars can use some more advanced carriage return, or even more advanced cursor positionning that are mostly not supported by treams. I've tried io.StringIO, but the \r is kept literal.

import io
from tqdm import tqdm
s = io.StringIO()
for i in tqdm(range(3), file=s):    
    sleep(.1)

输出:

s.getvalue()

Out[24]: '\n\r  0%|          | 0/3 [00:00<?, ?it/s]\x1b[A\n\r 33%|###3      | 1/3 [00:00<00:00,  9.99it/s]\x1b[A\n\r 67%|######6   | 2/3 [00:00<00:00,  9.98it/s]\x1b[A\n\r100%|##########| 3/3 [00:00<00:00,  9.98it/s]\x1b[A\n\x1b[A'

翻译为:

print(s.getvalue())
  0%|          | 0/3 [00:00<?, ?it/s]
 33%|###3      | 1/3 [00:00<00:00,  9.99it/s]
 67%|######6   | 2/3 [00:00<00:00,  9.98it/s]
100%|##########| 3/3 [00:00<00:00,  9.98it/s]

要清楚,在我的输出中,我不希望每个tqdm更新一行,而只希望当前状态,因为它将被打印在命令行上.

To be clear, in my output, I don't want one line per tqdm update, but just the current state, as it would be printed on the command line.

任何想法o如何做到这一点? 谢谢!

Any idea o how to do this ? Thanks!

推荐答案

该想法是,如果添加了新文本,则删除上一行,但是您还必须删除\r并确认它不是空文本.另外,要使对象接收tqdm的文本,它必须仅具有write()方法,因此请实现自定义QPlainTextEdit.使用QMetaObject::invokeMethod()使其具有线程安全性

The idea is to remove the previous line if there is a new text added, but you must also remove \r and verify that it is not an empty text. Also, for an object to receive the text of tqdm, it must only have the write() method, so implement a custom QPlainTextEdit. Use QMetaObject::invokeMethod() to make it thread-safe

import time
import threading
from tqdm import tqdm
from PyQt5 import QtCore, QtGui, QtWidgets
import lorem

class LogTextEdit(QtWidgets.QPlainTextEdit):
    def write(self, message):
        if not hasattr(self, "flag"):
            self.flag = False
        message = message.replace('\r', '').rstrip()
        if message:
            method = "replace_last_line" if self.flag else "appendPlainText"
            QtCore.QMetaObject.invokeMethod(self,
                method,
                QtCore.Qt.QueuedConnection, 
                QtCore.Q_ARG(str, message))
            self.flag = True
        else:
            self.flag = False

    @QtCore.pyqtSlot(str)
    def replace_last_line(self, text):
        cursor = self.textCursor()
        cursor.movePosition(QtGui.QTextCursor.End)
        cursor.select(QtGui.QTextCursor.BlockUnderCursor)
        cursor.removeSelectedText()
        cursor.insertBlock()
        self.setTextCursor(cursor)
        self.insertPlainText(text)

def foo(w):
    for i in tqdm(range(100), file=w):
        time.sleep(0.1)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = LogTextEdit(readOnly=True)
    w.appendPlainText(lorem.paragraph())
    w.appendHtml("Welcome to Stack Overflow")
    w.show()
    threading.Thread(target=foo, args=(w,), daemon=True).start()
    sys.exit(app.exec_())

这篇关于在QPlainTextEdit中使用tqdm显示终端输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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