我有一个Python软件,我用pyinstaller编译它。
如果发生任何错误,我想保存日志。通过保持软件快速,便携和智能,您认为在exe中这样做的最佳做法是什么?
答案 0 :(得分:0)
我有一个为此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)
这将捕获所有异常和回溯并将它们保存到文件中(包含时间和日期)以及程序中剩余的任何输出,例如print语句。此外,如果您在命令行(-d)上使用标志启动程序,则会显示一个窗口tkinter窗口,即使编译后也会实时回溯回溯(我已经使用cx_Freeze进行了测试)
答案 1 :(得分:-1)
我会通过在附加模式'a'中打开文件来记录。 一个简单的调试函数可能如下所示:
def debug(x):
fd = open("log.txt","a")
fd.write(time.ctime() + "\t" + x + "\n")
fd.close()