【问题标题】:Python and logging: best practice with .exePython 和日志记录:.exe 的最佳实践
【发布时间】:2017-05-11 10:12:40
【问题描述】:

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

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

【问题讨论】:

  • stdlib 的日志记录模块有什么问题? docs.python.org/2/library/logging.html
  • 我认为这个问题虽然可能没有措辞得那么好,但他想要捕获可能无法预料的错误(因此不用try: catch: 防范)并保存回溯看看哪里出了问题

标签: python logging pyinstaller


【解决方案1】:

我有一个为此编写的课程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 进行了测试)

【讨论】:

  • 我很抱歉,现在应该解决了。请注意,github 版本已经过调整,现在在交互式窗口中将 stdout 蓝色和 stderr 着色为红色。
【解决方案2】:

我会通过以附加模式“a”打开文件来记录。 一个简单的调试函数可能如下所示:

def debug(x):
    fd = open("log.txt","a")
    fd.write(time.ctime() + "\t" + x + "\n")
    fd.close()

【讨论】:

  • 没错,您必须手动记录所有内容。这已被证明对我非常有用,但我想它不是很漂亮。
  • 重点是Python在stdlib中有一个非常全面的logging包...
猜你喜欢
  • 1970-01-01
  • 2022-11-23
  • 1970-01-01
  • 1970-01-01
  • 2012-11-02
  • 1970-01-01
  • 2018-03-27
  • 2010-09-18
  • 2021-08-05
相关资源
最近更新 更多