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