【问题标题】:Python/QT Live Application Log in QMLQML 中的 Python/QT 实时应用程序日志
【发布时间】:2021-06-13 09:51:13
【问题描述】:

我正在尝试在 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)

【问题讨论】:

  • 更新了我的帖子
  • 如果您尝试创建类似 IDE 的应用程序,您可能应该在子进程中启动另一个 Python 实例。然后你可以很容易地抓住它的标准输出/标准错误; “沙盒”和“gui”环境也应该明确分开。您可以使用sys.prefix 获取当前解释器的可执行文件。
  • @Torben Klein 好的,很有趣。我知道如何创建另一个 Python 实例,但命令是什么? python3 sys.prefix?

标签: python logging pyqt pyside


【解决方案1】:

取决于您要捕获的内容:

定期日志消息?使用自己的日志处理程序:

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 对象属性中获取其输出。

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

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

编辑:如果您尝试创建类似 IDE 的应用程序,您可能应该在子进程中启动另一个 Python 实例。然后你可以很容易地抓住它的标准输出/标准错误; “沙盒”和“gui”环境也应该明确分开。

概念验证:

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

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

【讨论】:

  • 当我使用您的第一种方法时出现此错误。 AttributeError:“MyLogHandler”对象没有属性“格式化程序”。我复制了您的第一种方法并将 MyLogHandler() 添加到我的 handlers=[ ] 列表中。
  • 奇怪,在这里工作得很好......愚蠢的问题,你继承自logging.Handler吗?
  • 是的,我做到了,它不再显示错误,但是没有执行 emit 方法.. 奇怪
  • 你的概念证明似乎可行,只是对我来说有点老套。
  • 不要这么认为,实际上你应该这样做来执行“不受信任”的代码。除了记录之外,用户代码还可以做很多“损害”,例如僵尸线程、更改全局变量或函数、阻塞 I/O ......所以你会希望它在一个你可以杀死它并重新启动的环境中。
猜你喜欢
  • 2018-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
  • 1970-01-01
  • 2013-01-07
  • 1970-01-01
相关资源
最近更新 更多