首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python Logger实现

Python Logger实现
EN

Code Review用户
提问于 2023-04-08 01:16:56
回答 1查看 88关注 0票数 2

我已经用Python开发了一个记录器的实现。我知道Python已经有了内置的记录器,我的目标是获得改进的反馈和建议,特别是关于代码结构的建议。

代码在这里:

代码语言:javascript
复制
from .helpers import write_txt
from enum import Enum
from datetime import datetime


# Define type formats of messages
class LogFormats(Enum):
    TITLE = 'title'
    SUBTITLE = 'subtitle'
    ERROR = 'error'
    TAB = 'tab'
    DEFAULT = 'default'


# Handler functions for output messages with different formats

def format_title(message: str, time: str) -> str:
    to_print = f"\n[{time}] ### ### {message.upper()} ### ###\n"
    return to_print

def format_subtitle(message: str, time: str) -> str:
    to_print = f"[{time}] *** *** {message.upper()} *** ***"
    return to_print

def format_error(message: str, time: str) -> str:
    to_print = f"[{time}]\t  ERROR: {message}"
    return to_print

def format_tab(message: str, time: str) -> str:
    to_print = f"[{time}]\t  {message}"
    return to_print

def format_default(message: str, time: str) -> str:
    to_print = f"[{time}] - {message}"
    return to_print


# Handler functions dispatcher
FORMATTER_DISPATCH = {
    LogFormats.TITLE: format_title,
    LogFormats.SUBTITLE: format_subtitle,
    LogFormats.ERROR: format_error,
    LogFormats.TAB: format_tab,
    LogFormats.DEFAULT: format_default
}


class txtFileLogger():
    """Provides functionality for logging to a txt file"""
    registry: str = ''

    @classmethod
    def register_log(cls, msg: str) -> None:
        cls.registry = cls.registry + '\n' + msg

    @classmethod
    def output_log_to_txt(cls, filename = 'txt_log') -> None:
        write_txt(cls.registry, filename)


# ===================
#     MAIN CLASS
#====================

class Logger():
    """Format log messages and outputs it to the console. Also, provide methods for dumping the log session to a txt file."""
    txt_logger = txtFileLogger
    silenced = False

    @classmethod
    def log(cls,
            message: str,
            format: LogFormats = LogFormats.DEFAULT,
            hidden: bool = False
        ) -> None:
        """
        Logs a log message.

        This function logs a message and prints it to the console. The log type can be specified for different message formats. Also the console output can be toggled.

        Args:
            message (str): The message to be logged.
            type (LogTypes, optional): The log type.
            hidden (bool, optional): If set to True, hides the log in the console for this message. The message will be registered and dumped in txt file regardless of this option.
        """

        current_time = datetime.now().strftime("%H:%M:%S")
        msg = str(message)

        # Format log message according to selected type format
        log_type = LogFormats(format)
        formatter = FORMATTER_DISPATCH[log_type]
        formated_msg = formatter(msg, current_time)

        # Registers log for txt file output
        cls.txt_logger.register_log(formated_msg)

        # Print log to console
        if not hidden and not cls.silenced:
            print(formated_msg)
        
    @classmethod
    def dump_log_to_txt(cls, filename: str) -> None:
        """Writes log to a txt file"""
        cls.txt_logger.output_log_to_txt(filename)

    @classmethod
    def mute(cls) -> None:
        """Disables console output."""
        cls.silenced = True
        print('[Logger] -  *** Output to console is currently silenced ***')

    @classmethod
    def unmute(cls) -> None:
        """Enables console output."""
        cls.silenced = False
        print('[Logger] -  *** Enabling logging to console ***')

我使用类作为一种“单例”来实现这一点。因此,我可以在不同的文件中调用记录器,并为注册表提供一个单一的真实来源。使用示例:

代码语言:javascript
复制
import Logger

log = Logger.log

log('message 1', format='title')
log('message 2', format='subtitle')
log('error message', format='error')

Logger.dump_log_to_txt('foo_filename')

一些一般性问题:

  • 有没有办法提高我的记录器实现的效率?
  • 如何使我的代码更加可读性和良好的结构?

我感谢任何反馈意见和建议。谢谢!

EN

回答 1

Code Review用户

发布于 2023-04-08 15:41:29

您的所有format_函数都可以重构为具有命名参数的格式字符串,如

代码语言:javascript
复制
"\n[{time}] ### ### {message} ### ###\n"

然后可以通过.format(time=x, message=x)在一个位置进行格式化。

LogFormats相当困惑。其中一些条目是“严厉”(ERROR),一些是格式,其中一个是DEFAULT,应该设置为与DEFAULT = PLAIN这样的不同命名格式相等。

txtFileLogger需要在TitleCase中,因为它是一个类。另外,它应该是一个包含文件名成员的非静态类,write_txt应该作为一个成员函数移到它中。每个目标文件应该有一个实例。

不继承任何东西的类不应该接收()后缀。

Logger也应该是一个非静态类。如果一个记录员被迫成为一个单身人士,那是没有帮助的。至多,让Logger成为一个普通类,既可以实例化,也可以提供默认的全局实例。

hidden很尴尬。您已经有效地对一个机制进行了硬编码,其中一个文件的最小严重性低于控制台。看看内置记录器是如何做到这一点的;您可以将控制台和文件配置成不同的严重程度,然后客户端可能会幼稚到哪个目标关心哪个严重程度,并为每个日志条目提供一个单一的严重性。

“效率”是一个很有意义的术语。使用内置记录器。如果您试图推送如此多的日志量,以致内置记录器在时间或空间上是一个限制因素,那么您可能记录太多,而不是试图优化一个主卷版本,您应该限制您的日志记录。以一种非结构化的方式有效地记录的东西是有上限的。(结构化日志是一个不同的主题。)在这方面,对效率的担忧是过早的优化。

对于实践来说,好吧,我想,但在现实生活中,不要这样做,而使用内置记录器。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/284365

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档