gpt4 book ai didi

Python:结合日志记录和 wx,以便将日志流重定向到 stdout/stderr 框架

转载 作者:行者123 更新时间:2023-11-28 17:54:32 27 4
gpt4 key购买 nike

事情是这样的:

我正在尝试将日志记录模块与 wx.App() 的重定向功能相结合。我的意图是登录到文件 AND 到 stderr。但我希望 stderr/stdout 重定向到一个单独的框架,就像 wx.App 的功能一样。

我的测试代码:

import logging
import wx

class MyFrame(wx.Frame):
def __init__(self):
self.logger = logging.getLogger("main.MyFrame")
wx.Frame.__init__(self, parent = None, id = wx.ID_ANY, title = "MyFrame")
self.logger.debug("MyFrame.__init__() called.")

def OnExit(self):
self.logger.debug("MyFrame.OnExit() called.")

class MyApp(wx.App):
def __init__(self, redirect):
self.logger = logging.getLogger("main.MyApp")
wx.App.__init__(self, redirect = redirect)
self.logger.debug("MyApp.__init__() called.")

def OnInit(self):
self.frame = MyFrame()
self.frame.Show()
self.SetTopWindow(self.frame)
self.logger.debug("MyApp.OnInit() called.")
return True

def OnExit(self):
self.logger.debug("MyApp.OnExit() called.")

def main():
logger_formatter = logging.Formatter("%(name)s\t%(levelname)s\t%(message)s")
logger_stream_handler = logging.StreamHandler()
logger_stream_handler.setLevel(logging.INFO)
logger_stream_handler.setFormatter(logger_formatter)
logger_file_handler = logging.FileHandler("test.log", mode = "w")
logger_file_handler.setLevel(logging.DEBUG)
logger_file_handler.setFormatter(logger_formatter)
logger = logging.getLogger("main")
logger.setLevel(logging.DEBUG)
logger.addHandler(logger_stream_handler)
logger.addHandler(logger_file_handler)
logger.info("Logger configured.")

app = MyApp(redirect = True)
logger.debug("Created instance of MyApp. Calling MainLoop().")
app.MainLoop()
logger.debug("MainLoop() ended.")
logger.info("Exiting program.")

return 0

if (__name__ == "__main__"):
main()

预期行为是:
- 创建一个名为 test.log 的文件
- 该文件包含级别为 DEBUG 和 INFO/ERROR/WARNING/CRITICAL 的日志消息
- 来自 INFO 和 ERROR/WARNING/CRITICAL 类型的消息要么显示在控制台上,要么显示在单独的框架中,具体取决于它们的创建位置
- 不在 MyApp 或 MyFrame 中的记录器消息显示在控制台
- 来自 MyApp 或 MyFrame 内部的记录器消息显示在单独的框架中

实际行为是:
- 文件已创建并包含:

main    INFO    Logger configured.
main.MyFrame DEBUG MyFrame.__init__() called.
main.MyFrame INFO MyFrame.__init__() called.
main.MyApp DEBUG MyApp.OnInit() called.
main.MyApp INFO MyApp.OnInit() called.
main.MyApp DEBUG MyApp.__init__() called.
main DEBUG Created instance of MyApp. Calling MainLoop().
main.MyApp DEBUG MyApp.OnExit() called.
main DEBUG MainLoop() ended.
main INFO Exiting program.

- 控制台输出为:

main    INFO    Logger configured.
main.MyFrame INFO MyFrame.__init__() called.
main.MyApp INFO MyApp.OnInit() called.
main INFO Exiting program.

- 没有单独的框架被打开,尽管线条

main.MyFrame    INFO    MyFrame.__init__() called.
main.MyApp INFO MyApp.OnInit() called.

应该显示在一个框架内,而不是在控制台上。

在我看来,只要记录器实例使用 stderr 作为输出,wx.App 就无法将 stderr 重定向到一个框架。 wxPythons Docs 声明了想要的行为,see here.

有什么想法吗?

乌维

最佳答案

当 wx.App 说它会将 stdout/stderr 重定向到一个弹出窗口时,它的真正意思是它将重定向 sys.stdout 和 sys.stderr,所以如果你直接写入 sys.stdout 或 sys.stderr 它将被重定向到弹出窗口,例如试试这个

print "this will go to wx msg frame"
sys.stdout.write("yes it goes")
sys.stderr.write("... and this one too")

这里的问题是如果 wxApp 在创建 streamhandler 之后创建,streamhandler 指向旧的(原始的)sys.stderr 和 sys.stdout 而不是 wxApp 设置的新的,所以一个更简单的解决方案是创建 wx.App在创建 streap 处理程序之前,例如在代码中移动 app = MyApp(redirect = True) 在记录初始化代码之前。

或者创建自定义日志处理程序并将数据写入 sys.stdout 和 sys.stderr,或者更好地创建您自己的窗口并在其中添加数据。例如试试这个

class LogginRedirectHandler(logging.Handler):
def __init__(self,):
# run the regular Handler __init__
logging.Handler.__init__(self)

def emit(self, record):
sys.stdout.write(record.message)

loggingRedirectHandler = LogginRedirectHandler()
logger_file_handler.setLevel(logging.DEBUG)
logger.addHandler(loggingRedirectHandler)

关于Python:结合日志记录和 wx,以便将日志流重定向到 stdout/stderr 框架,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2689441/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com