Python/QT QML 中的实时应用程序日志

Python/QT Live Application Log in QML

我正在尝试在 QML GUI 中创建所有控制台输出的实时日志。 我想在每次 Python 写入 stdout/stderr 时发出一个 QT 信号。我正在使用 Python 3.8。这是我的代码,它通过写入文件和控制台来执行 QML 输出和 Python 解释器 stderr 的日志记录。

class Log(QObject, object):

    def __init__(self):
        logging.basicConfig(
            level=logging.DEBUG,
            format="%(asctime)s [%(levelname)s] %(message)s",
            handlers=[
                logging.FileHandler("debug.log", mode='w'),
                logging.StreamHandler()
            ]
        )
        qInstallMessageHandler(self.qt_message_handler)

    def qt_message_handler(self, mode, context, message):
        log_entry = "%s: %s (%s:%d, %s)" % (mode.name.decode(), message, context.file, context.line, context.file)
        logging.warning(log_entry)

取决于您要捕获的内容:

常规日志消息?使用自己的日志处理程序:

class MyLogHandler(logging.Handler):
    def emit(self, record):
        """Do whatever you need with the record"""
# somewhere appropriate
logging.getLogger().addHandler(MyLogHandler())

打印语句的输出?您可以捕获并转换为日志消息。我在我的程序中使用类似这样的东西来捕获剩余的 print() 调用:

real_print = print
def _print(*stuff, sep=' ', end='\n', file=sys.stdout, flush):
    if not (file is sys.stdout or file is None):
        return real_print(*stuff, sep=sep, end=end, file=file, flush=flush)
    text = sep.join(str(thing) for thing in stuff)
    # replace by other logging call as desired
    # e.g. add file / lineno information
    logging.info(text)
__builtins__['print'] = _print

stdout / stderr(C 库)的不受管制的输出:这有点复杂。如果可能,您可以将输出内容的代码部分隔离到 subprocess 中。然后您可以从 Subprocess 对象属性中获取它的输出。

否则,您可以 fiddle 使用 sys.stdout / sys.stderr,但我怀疑这对 C 库没有帮助(我自己从未尝试过)。

无论如何,在处理日志时要格外小心错误处理。消失的日志消息是享受数小时调试乐趣的门票。

编辑:如果您正在尝试创建类似 IDE 的应用程序,您可能应该在子进程中启动另一个 Python 实例。然后你就可以轻松抓住它的stdout/stderr; “sandbox”和“gui”环境也应该明确分开。

概念验证:

import sys
import subprocess
# runs python --version
sp = subprocess.run([sys.executable, "--version"])
print(sp.stdout)

对于“真正的”工作,您当然会省略 --version arg,并以某种方式将输入发送到 sp.stdin。