Python和日志记录:使用.exe的最佳实践

时间:2017-05-11 10:12:40

标签: python logging pyinstaller

我有一个Python软件,我用pyinstaller编译它。

如果发生任何错误,我想保存日志。通过保持软件快速,便携和智能,您认为在exe中这样做的最佳做法是什么?

2 个答案:

答案 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()