# -*- coding: utf-8 -*- # !/usr/bin/env python import logging import logging.handlers import os import sys import time __all__ = ['set_logger', 'debug', 'info', 'warning', 'error', 'critical', 'exception'] # Color escape string COLOR_RED = '\033[1;31m' COLOR_GREEN = '\033[1;32m' COLOR_YELLOW = '\033[1;33m' COLOR_BLUE = '\033[1;34m' COLOR_PURPLE = '\033[1;35m' COLOR_CYAN = '\033[1;36m' COLOR_GRAY = '\033[1;37m' COLOR_WHITE = '\033[1;38m' COLOR_RESET = '\033[1;0m' # Define log color LOG_COLORS = { 'DEBUG': '%s', 'INFO': COLOR_GREEN + '%s' + COLOR_RESET, 'WARNING': COLOR_YELLOW + '%s' + COLOR_RESET, 'ERROR': COLOR_RED + '%s' + COLOR_RESET, 'CRITICAL': COLOR_RED + '%s' + COLOR_RESET, 'EXCEPTION': COLOR_RED + '%s' + COLOR_RESET, } # Global logger g_logger = None class ColoredFormatter(logging.Formatter): """A colorful formatter.""" def __init__(self, fmt=None, datefmt=None): logging.Formatter.__init__(self, fmt, datefmt) def format(self, record): level_name = record.levelname msg = logging.Formatter.format(self, record) return LOG_COLORS.get(level_name, '%s') % msg def add_handler(cls, level, fmt, colorful, **kwargs): """Add a configured handlers to the global logger.""" global g_logger if isinstance(level, str): level = getattr(logging, level.upper(), logging.INFO) handler = cls(**kwargs) handler.setLevel(level) if colorful: formatter = ColoredFormatter(fmt) else: formatter = logging.Formatter(fmt) handler.setFormatter(formatter) g_logger.addHandler(handler) return handler def add_stream_handler(level, fmt): """Add a stream handlers to the global logger.""" return add_handler(logging.StreamHandler, level, fmt, True) def add_file_handler(level, fmt, filename, mode, backup_count, limit, when): """Add a file handlers to the global logger.""" kwargs = {} # If the filename is not set, use the default filename if filename is None: logs_directory = os.path.join(os.path.dirname(__file__), os.pardir) + "/logs" if os.path.isdir(logs_directory) is not True: os.mkdir(logs_directory) filename = logs_directory + os.sep + 'anal' + '.log' kwargs['filename'] = filename # Choose the file_handler based on the passed arguments if backup_count == 0: # Use FileHandler cls = logging.FileHandler kwargs['mode'] = mode elif when is None: # Use RotatingFileHandler cls = logging.handlers.RotatingFileHandler kwargs['maxBytes'] = limit kwargs['backupCount'] = backup_count kwargs['mode'] = mode else: # Use TimedRotatingFileHandler cls = logging.handlers.TimedRotatingFileHandler kwargs['when'] = when kwargs['interval'] = 1 # 1个单位 kwargs['backupCount'] = backup_count return add_handler(cls, level, fmt, False, **kwargs) def init_logger(): """Reload the global logger.""" global g_logger if g_logger is None: g_logger = logging.getLogger() else: logging.shutdown() g_logger.handlers = [] g_logger.setLevel(logging.DEBUG) def set_logger(filename=None, mode='a', level='INFO', fmt=None, backup_count=5, limit=20480000, when='midnight'): """Configure the global logger.""" level = level.split(':') if len(level) == 1: # Both set to the same level s_level = f_level = level[0] else: s_level = level[0] # StreamHandler log level f_level = level[1] # FileHandler log level if fmt is None: if s_level == 'ERROR' or f_level == 'ERROR': fmt = '[%(levelname)s] %(asctime)s %(message)s in \'%(filename)s:%(lineno)s\'' else: fmt = '[%(levelname)s] %(asctime)s %(message)s' init_logger() add_stream_handler(s_level, fmt) add_file_handler(f_level, fmt, filename, mode, backup_count, limit, when) # Import the common log functions for convenient import_log_funcs() def import_log_funcs(): """Import the common log functions from the global logger to the module.""" global g_logger curr_mod = sys.modules[__name__] log_funcs = ['debug', 'info', 'warning', 'error', 'critical', 'exception'] for func_name in log_funcs: func = getattr(g_logger, func_name) setattr(curr_mod, func_name, func) # Set a default logger set_logger()