一个彩色的Logging日志,后续调用的时候,可以直接引用

1、logger名字为日期

一个彩色的日志,用于在输出框里输出彩色字体,并在文件保持处生成正常的字体

1.1、日志样式

----your_file.py
----log
-------2023_2_10.log

1.2、实现方法

我这里的命名方式为:colors_logger.py

# -*- coding: utf-8 -*
# @Time    : 2024/8/14 15:08
# @Author  : huakuohao
# @File    : colors_logger.py
# @Project : B_daily_Project
# @Software: PyCharm
# love 
# If I can't be a god, I'll be a beast

import logging
import sys
import os
import time

# 公众号:右恩
class TerminalColor:
    RED = '\033[91m'
    GREEN = '\033[92m'
    YELLOW = '\033[93m'
    RESET = '\033[0m'
    BLUE = '\033[94m'
    MAGENTA = '\033[95m'
    CYAN = '\033[96m'
    WHITE = '\033[97m'
'''
30:黑色
31:红色
32:绿色
33:黄色(或称为棕色或橄榄色)
34:蓝色
35:品红(或称为紫色)
36:青色(或称为蓝绿色)
37:白色
90-97:亮色版本(亮黑、亮红、亮绿、亮黄、亮蓝、亮品红、亮青、亮白)
'''

class ColorFormatter(logging.Formatter):
    COLORS = {
        logging.DEBUG: TerminalColor.CYAN,
        logging.INFO: TerminalColor.BLUE,
        logging.WARNING: TerminalColor.MAGENTA,
        logging.ERROR: TerminalColor.RED,
        logging.CRITICAL: TerminalColor.GREEN
    }

    def format(self, record):
        level_color = self.COLORS.get(record.levelno, TerminalColor.RESET)
        reset_color = TerminalColor.RESET
        message = super().format(record)
        return f"{level_color}{message}{reset_color}"
def _reset_logger(log):
    for handler in log.handlers:
        handler.close()
        log.removeHandler(handler)
        del handler
    log.handlers.clear()
    log.propagate = False
    console_handle = logging.StreamHandler(sys.stdout)
    console_handle.setFormatter(
        ColorFormatter(
            "%(asctime)s- %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s",
            datefmt="%H:%M:%S",
        )
    )
    log_name = os.path.join(_ensure_log_path(), f"{time.strftime('%Y_%m_%d')}.log")
    file_handle = logging.FileHandler(log_name, encoding="utf-8")
    file_handle.setFormatter(
        logging.Formatter(
            "[%(asctime)s][%(levelname)s][%(filename)s:%(lineno)d] - %(message)s",
            datefmt="%Y-%m-%d %H:%M:%S",
        )
    )
    log.addHandler(file_handle)
    log.addHandler(console_handle)
# 公众号:右恩
def _ensure_log_path():
    log_path = os.path.join(os.getcwd(), 'logs')
    os.makedirs(log_path, exist_ok=True)
    return log_path

def _get_logger():
    log = logging.getLogger("log")
    _reset_logger(log)
    log.setLevel(logging.DEBUG)
    return log


# 日志句柄
logger = _get_logger()

if __name__ == '__main__':
    logger.info('This is an info message')
    logger.debug('This is a debug message')
    logger.warning('This is a warning message')
    logger.error('This is an error message')
    logger.critical('This is a critical message')

后续调用

from colors_logger import logger
logger.info("这是一个日志")
# 公众号:右恩

调用后的文件位置

----your_file.py
----log
-------2023_2_10.log

2、当前文件名的日志

2.1日志样式

----your_file.py
----log
-------your_file_log.log

2.2实现方法

# -*-coding:utf-8 -*-
import logging
import sys
import os
import time
import inspect
import re


class TerminalColor:
    RED = '\033[91m'
    GREEN = '\033[92m'
    YELLOW = '\033[93m'
    RESET = '\033[0m'
    BLUE = '\033[94m'
    MAGENTA = '\033[95m'
    CYAN = '\033[96m'
    WHITE = '\033[97m'

# 公众号:右恩
class ColorFormatter(logging.Formatter):
    COLORS = {
        logging.DEBUG: TerminalColor.CYAN,
        logging.INFO: TerminalColor.BLUE,
        logging.WARNING: TerminalColor.MAGENTA,
        logging.ERROR: TerminalColor.RED,
        logging.CRITICAL: TerminalColor.GREEN
    }

    def format(self, record):
        level_color = self.COLORS.get(record.levelno, TerminalColor.RESET)
        reset_color = TerminalColor.RESET
        message = super().format(record)
        return f"{level_color}{message}{reset_color}"


def _sanitize_filename(name):
    """清理非法文件名字符"""
    # Windows非法字符:<>:"/\|?* 以及ASCII控制字符(0-31)
    return re.sub(r'[<>:"/\\|?*\x00-\x1f]', '', name).strip()

# 公众号:右恩
def _get_valid_caller():
    """获取有效的调用者信息"""
    stack = inspect.stack()
    for frame_info in stack:
        filename = frame_info.filename
        # 跳过当前文件和非文件路径
        if filename == __file__:
            continue
        if not os.path.exists(filename):
            continue
        if '<' in filename or '>' in filename:
            continue
        return filename
    return None


def _get_caller_filename():
    """安全获取调用者文件名"""
    valid_path = _get_valid_caller()
    if valid_path:
        base_name = os.path.splitext(os.path.basename(valid_path))[0]
        return _sanitize_filename(base_name) or "default_log"
    return "default_log"


def _ensure_log_path():
    log_path = os.path.join(os.getcwd(), 'logs')
    os.makedirs(log_path, exist_ok=True)
    return log_path

# 公众号:右恩
def _reset_logger(log):
    # 清除现有handler
    for handler in log.handlers[:]:
        handler.close()
        log.removeHandler(handler)

    # 控制台handler
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setFormatter(
        ColorFormatter(
            "%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s",
            datefmt="%H:%M:%S"
        )
    )

    # 文件handler
    caller_name = _get_caller_filename()
    safe_name = f"{caller_name}_log.log"
    log_name = os.path.join(_ensure_log_path(), safe_name)

    try:
        file_handler = logging.FileHandler(log_name, encoding="utf-8")
    except Exception as e:
        sys.stderr.write(f"无法创建日志文件 {log_name}: {str(e)}\n")
        file_handler = logging.FileHandler("fallback.log", encoding="utf-8")

    file_handler.setFormatter(
        logging.Formatter(
            "[%(asctime)s][%(levelname)s][%(filename)s:%(lineno)d] - %(message)s",
            datefmt="%Y-%m-%d %H:%M:%S"
        )
    )

    # 添加handler# 公众号:右恩
    log.addHandler(console_handler)
    log.addHandler(file_handler)
    log.propagate = False


def _get_logger():
    log = logging.getLogger("safe_dynamic_logger")
    if not log.handlers:
        _reset_logger(log)
    log.setLevel(logging.DEBUG)
    return log


# 全局日志对象
logger = _get_logger()

if __name__ == '__main__':
    logger.debug("Debug测试信息")
    logger.info("当前日志文件:", extra={"skip_special_check": True})

3、当前文件名加时间的日志

3.1日志样式

----your_file.py
----log
-------your_file_log_2025_03_03_12_20_30.log

3.2实现方法

# -*-coding:utf-8 -*-
import logging
import sys
import os
import time
import inspect
import re


class TerminalColor:
    RED = '\033[91m'
    GREEN = '\033[92m'
    YELLOW = '\033[93m'
    RESET = '\033[0m'
    BLUE = '\033[94m'
    MAGENTA = '\033[95m'
    CYAN = '\033[96m'
    WHITE = '\033[97m'


class ColorFormatter(logging.Formatter):
    COLORS = {
        logging.DEBUG: TerminalColor.CYAN,
        logging.INFO: TerminalColor.BLUE,
        logging.WARNING: TerminalColor.MAGENTA,
        logging.ERROR: TerminalColor.RED,
        logging.CRITICAL: TerminalColor.GREEN
    }

    def format(self, record):
        level_color = self.COLORS.get(record.levelno, TerminalColor.RESET)
        reset_color = TerminalColor.RESET
        message = super().format(record)
        return f"{level_color}{message}{reset_color}"


def _sanitize_filename(name):
    """清理非法文件名字符"""
    return re.sub(r'[<>:"/\\|?*\x00-\x1f]', '', name).strip()


def _get_valid_caller():
    stack = inspect.stack()
    for frame_info in stack:
        filename = frame_info.filename
        if filename == __file__: continue
        if not os.path.exists(filename): continue
        if '<' in filename or '>' in filename: continue
        return filename
    return None


def _get_caller_filename():
    valid_path = _get_valid_caller()
    if valid_path:
        base_name = os.path.splitext(os.path.basename(valid_path))[0]
        return _sanitize_filename(base_name) or "default_log"
    return "default_log"


def _ensure_log_path():
    log_path = os.path.join(os.getcwd(), 'logs')
    os.makedirs(log_path, exist_ok=True)
    return log_path


def _generate_timestamp():
    """生成标准时间戳字符串"""
    return time.strftime("%Y_%m_%d_%H_%M_%S")


def _reset_logger(log):
    # 清除现有handler
    for handler in log.handlers[:]:
        handler.close()
        log.removeHandler(handler)

    # 控制台输出配置
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setFormatter(
        ColorFormatter(
            "%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s",
            datefmt="%H:%M:%S"
        )
    )

    # 文件输出配置(新增时间戳)
    caller_name = _get_caller_filename()
    timestamp = _generate_timestamp()
    safe_name = f"{caller_name}_log_{timestamp}.log"  # 格式:test1_log_2025_03_03_12_20_30.log
    log_name = os.path.join(_ensure_log_path(), safe_name)

    try:
        file_handler = logging.FileHandler(log_name, encoding="utf-8")
    except Exception as e:
        sys.stderr.write(f"创建日志文件失败: {str(e)}\n")
        file_handler = logging.FileHandler("fallback.log", encoding="utf-8")

    file_handler.setFormatter(
        logging.Formatter(
            "[%(asctime)s][%(levelname)s][%(filename)s:%(lineno)d] - %(message)s",
            datefmt="%Y-%m-%d %H:%M:%S"
        )
    )

    log.addHandler(console_handler)
    log.addHandler(file_handler)
    log.propagate = False


def _get_logger():
    log = logging.getLogger("timestamp_logger")
    if not log.handlers:
        _reset_logger(log)
    log.setLevel(logging.DEBUG)
    return log


# 全局日志对象
logger = _get_logger()

if __name__ == '__main__':
    # 验证日志文件名生成
    logger.info("测试时间戳日志文件名")
    print("生成的日志文件:", [f for f in os.listdir('logs') if f.endswith('.log')])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值