我有一个为此编写的课程here
import logging
import sys
import tkinter as tk
from tkinter import messagebox
from tkinter.scrolledtext import ScrolledText
__all__ = ["logging",
"StreamToLogger",
"Debug_Logger"]
class StreamToLogger(object):
def __init__(self, logger, log_level=logging.INFO):
self.logger = logger
self.log_level = log_level
self.error_types = ["AssertionError", "AttributeError",
"EOFError", "FloatingPointError",
"GeneratorExit", "ImportError",
"IndexError", "KeyError",
"KeyboardInterrupt", "MemoryError",
"NameError", "NotImplementedError",
"OSError", "OverflowError",
"ReferenceError", "RuntimeError",
"StopIteration", "SyntaxError",
"IndentationError", "TabError",
"SystemError", #"SystemExit", #included for completeness, but illogical to log a normal exit
"TypeError", "UnboundLocalError",
"UnicodeError", "UnicodeEncodeError",
"UnicodeDecodeError", "UnicodeTranslateError",
"ValueError", "ZeroDivisionError",
"EnvironmentError", "IOError",
"WindowsError", "BlockingIOError",
"ChildProcessError", "ConnectionError",
"BrokenPipeError", "ConnectionAbortedError",
"ConnectionRefusedError", "ConnectionResetError",
"FileExistsError", "FileNotFoundError",
"InterruptedError", "IsADirectoryError",
"NotADirectoryError", "PermissionError",
"ProcessLookupError", "TimeoutError",]
def write(self, buf):
for line in buf.rstrip().splitlines():
self.logger.log(self.log_level, line.rstrip())
for entry in self.error_types:
if entry in str(buf):
root = tk.Tk()
root.withdraw()
messagebox.showwarning("Warning", "An error has occured,\ncheck error log")
root.destroy()
def flush(self):
pass
class DebugLogger(object):
def __init__(self):
self.GUI = tk.Toplevel()
self.GUI.protocol('WM_DELETE_WINDOW', self.GUI.withdraw)
self.GUI.title("Debug Console")
self.textbox = ScrolledText(self.GUI)
self.textbox.configure(state = "disabled")
self.textbox.pack(fill = "both", expand = True)
self.GUI.focus()
def write(self, buf):
self.textbox.configure(state = "normal")
self.textbox.insert(tk.END, str(buf))
self.textbox.configure(state = "disabled")
self.textbox.see("end")
def flush(self):
pass
你可以这样使用:
import logging, sys
if ("-d" in sys.argv) or ("-D" in sys.argv):
debugger = Debug_Logger()
sys.stdout = debugger
sys.stderr = debugger
else:
logdir = os.getenv("APPDATA") + "\\applicationame\\"
if not os.path.isdir(logdir):
os.makedirs(logdir)
logfile = logdir + "applicationname.log"
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s:%(levelname)s:%(name)s:%(message)s', filename=logfile, filemode='w')
sys.stdout = StreamToLogger(logging.getLogger('STDOUT'), logging.INFO)
sys.stderr = StreamToLogger(logging.getLogger('STDERR'), logging.ERROR)
这将捕获所有异常和回溯并将它们保存到文件中(带有时间和日期)以及程序中留下的任何输出,例如打印语句。此外,如果您在命令行 (-d) 上使用标志启动程序,则会显示一个窗口 tkinter 窗口,即使在编译后也能实时显示回溯(我已经使用 cx_Freeze 进行了测试)