zoukankan      html  css  js  c++  java
  • python+logging

    日志按照下面四个层次来完成日志的功能

    1  Logger暴露出来给应用使用的接口

    2  Handlers是发送日志记录(由logger创建的)到合适的目的地,包括文件,屏幕,email...

    3  Filters 是提供一个过滤的机制,决定哪些日志可以留下

    4  Formatters是输出日志的格式

    创建格式:

    logger = logging.getLogger('apps') # 创建一个新的apps 的logger
    
    logger.setLevel(logging.DEBUG)  # 因为它是会默认传播到祖先logger
    
    logger.propagate = False  # 默认StreamHandler那里, 也就是不会打印在页面上
    
    apps_handler = logging.FileHandler(filename="apps.log")  # 添加handler, 决定日志落地到哪里,可以多个
    
    apps_formatter=logging.Formatter('%(asctime)s:%(name)s:%(levelname)s:%(message)s'  # 输出日志的格式
    
    apps_handler.setFormatter(apps_formatter)  # 装载上
    
    logger.addHandler(apps_handler)  # 装载实例化logger上
    
    # 日志会打印到apps.log, 并且不会输出到屏幕(如果logger.propagate=True就会)

    继承;

    # 定义一个新的logger
    
    child_logger = logging.getLogger('apps.owan')
    
    # 因为这个child_logger 是apps.owan, 它是继承了apps这个logger
    
    # 这个child_logger.propagate 默认是True
    
    # 所以还是会传到它的祖先logger 也就是apps
    
    child_logger.info('haha')
    
    # 所以这个info 是会传播到apps 所以apps.log会出现这个日志。
    
    # 这里充分说明logger的继承关系

    定义Log两种方法

    第一种:就是实例化logger = logging.logger 然后手动给logger添加addHandler, addFilter, handler.setFormatter 添加格式,这样的形式来获取logger。。。。。

    import logging
    
    # 没有创建logger, 默认是root logger, 直接打印在屏幕
    
    logging.basicConfig(level=logging.DEBUG,format='%(asctime)s:%(name)s:%(levelname)s:%(message)s')                                                                                             
    
    logger = logging.getLogger('apps')
    
    apps_handler = logging.FileHandler(filename="apps.log")
    
    logger.addHandler(apps_handler)
    
    logger.setLevel(logging.DEBUG)
    
    logger.info('shis')

    第二种:就是使用 logging.config.dictConfig 来从配置文件生成logger

    logging.config.dictConfig(log_config.PATTERN)
    
    # 没有定义的logger
    
    tool_logger = logging.getLogger('ToolApi')
    
    # 由于没有定义,会冒泡到root logger
    
    tool_logger.info('----------------')
    
    # 定义过的api logger
    
    api_logger = logging.getLogger('API')
    
    # 定义过了,所以api自己的handler会处理,同时会冒泡到root logger处理
    
    api_logger.error('fuck !')

    配置文件:

    PATTERN = {
    
        'version': 1,
    
        'formatters': {
    
            'normal': {
    
                'format': '%(name)s %(asctime)s %(levelname)s %(message)s',
    
                'datefmt': '%Y-%m-%d %H:%M:%S'
    
            },
    
            'raw': {
    
                'format': '%(message)s',
    
            },
    
        },
    
        'handlers': {
    
            'console': {
    
                'class': 'logging.StreamHandler',
    
                'stream': 'ext://sys.stdout',
    
                'formatter': 'normal',
    
            },
    
            'root': {
    
                'class': 'logging.handlers.WatchedFileHandler',
    
                'formatter': 'normal',
    
                'filename': RUNTIME_HOME + '/var/log/root.log',
    
                'mode': 'a',
    
                'level': 'INFO',
    
            },
    
            'extapi': {
    
                'class': 'logging.handlers.WatchedFileHandler',
    
                'formatter': 'normal',
    
                'filename': RUNTIME_HOME + '/var/log/ext_api.log',
    
                'mode': 'a',
    
                'level': 'DEBUG',
    
            },
    
            'api': {
    
                'class': 'logging.handlers.WatchedFileHandler',
    
                'formatter': 'normal',
    
                'filename': RUNTIME_HOME + '/var/log/api.log',
    
                'mode': 'a',
    
                'level': 'DEBUG',
    
            },
    
        },
    
        'loggers': {
    
            'API': {'level': 'DEBUG',
    
                    'handlers': ['api'],
    
                    },
    
            'EXTAPI': {'level': 'DEBUG',
    
                       'handlers': ['extapi'],
    
                       },
    
            'requests.packages.urllib3.connectionpool': {'level': 'ERROR'},
    
        },
    
        'root': {
    
            'handlers': ['root',],
    
            'level': 'INFO',
    
        }
    
    }

    例子:

    import logging
    
    import os
    
    from douban_scrapy import settings
    
    from logging.handlers import RotatingFileHandler
    
    from logging import StreamHandler
    
     
    
    # 直接继承logging.Logger 那么就是说这个类就是一个Logger, 有了Logger所有方法
    
    # 只是在类里面添加一些内部方法,让logger 封装addhandler, setformatter等方法
    
    class LogHandler(logging.Logger):
    
        # 单例模式
    
        _instance = None
    
        def __new__(cls, *args, **kwargs):
    
            if not cls._instance:
    
                # 一开始居然用了 cls()来实例化 导致无限次调用
    
                # cls._instance = cls(*args, **kwargs)
    
                cls._instance = object.__new__(cls, *args, **kwargs)
    
            return cls._instance
    
     
    
        def __init__(self, name, level=logging.DEBUG, to_stream=True, to_file=True):
    
            self.name = name
    
            self.level = level
    
            self.formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
    
            # 错误的, 继承了logger 本身就是logger 不用再self.logger=xxx 这样变成了一个新的变量
    
            #self.logger = logging.Logger(name=name, level=level)
    
            super(LogHandler, self).__init__(name=name, level=level)
    
     
    
            # 写文件
    
            if to_file:
    
                self.__setFileHandler__()
    
     
    
            # 写标准输出
    
            if to_stream:
    
                self.__setSteamHandler__()
    
     
    
        def __setSteamHandler__(self):
    
            stream_handler = StreamHandler()
    
            stream_handler.setFormatter(self.formatter)
    
            self.addHandler(stream_handler)
    
     
    
        def __setFileHandler__(self):
    
            log_path = os.path.join(settings.LOG_DIR, self.name +'.log')
    
            handler = RotatingFileHandler(log_path, maxBytes=1024, backupCount=5)
    
            handler.setFormatter(self.formatter)
    
            self.addHandler(handler)
    
     
     
    
    if __name__ == '__main__':
    
        logger = LogHandler('scrapy')
    
        logger2 = LogHandler('scrapy')
    
        print logger, logger2
    
    logger.info('haha')

    2:-----------------------------------------------------------------------------------------------------------------------2

    import os
    
    import logging
    
    from logging.handlers import TimedRotatingFileHandler
    
     
    
    # 日志级别
    
    CRITICAL = 50
    
    FATAL = CRITICAL
    
    ERROR = 40
    
    WARNING = 30
    
    WARN = WARNING
    
    INFO = 20
    
    DEBUG = 10
    
    NOTSET = 0
    
     
    
    CURRENT_PATH = os.path.dirname(os.path.abspath(__file__))
    
    ROOT_PATH = os.path.join(CURRENT_PATH, os.pardir)
    
    LOG_PATH = os.path.join(ROOT_PATH, 'log')
    
     
    
     
    
    class LogHandler(logging.Logger):
    
        """
    
        LogHandler
    
        """
    
     
    
        def __init__(self, name, level=DEBUG, stream=True, file=True):
    
            self.name = name
    
            self.level = level
    
            logging.Logger.__init__(self, self.name, level=level)
    
            if stream:
    
                self.__setStreamHandler__()
    
            if file:
    
                self.__setFileHandler__()
    
     
    
        def __setFileHandler__(self, level=None):
    
            """
    
            set file handler
    
            :param level:
    
            :return:
    
            """
    
            file_name = os.path.join(LOG_PATH, '{name}.log'.format(name=self.name))
    
            # 设置日志回滚, 保存在log目录, 一天保存一个文件, 保留15天
    
            file_handler = TimedRotatingFileHandler(filename=file_name, when='D', interval=1, backupCount=15)
    
            file_handler.suffix = '%Y%m%d.log'
    
            if not level:
    
                file_handler.setLevel(self.level)
    
            else:
    
                file_handler.setLevel(level)
    
            formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
    
     
    
            file_handler.setFormatter(formatter)
    
            self.file_handler = file_handler
    
            self.addHandler(file_handler)
    
     
    
        def __setStreamHandler__(self, level=None):
    
            """
    
            set stream handler
    
            :param level:
    
            :return:
    
            """
    
            stream_handler = logging.StreamHandler()
    
            formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
    
            stream_handler.setFormatter(formatter)
    
            if not level:
    
                stream_handler.setLevel(self.level)
    
            else:
    
                stream_handler.setLevel(level)
    
            self.addHandler(stream_handler)
    
     
    
        def resetName(self, name):
    
            """
    
            reset name
    
            :param name:
    
            :return:
    
            """
    
            self.name = name
    
            self.removeHandler(self.file_handler)
    
            self.__setFileHandler__()
    
     
    
    if __name__ == '__main__':
    
        log = LogHandler('test')
    
        log.info('this is a test msg')
  • 相关阅读:
    hdu1506(dp)
    windows下安装JMeter
    phpstudy 80端口被占用,修改端口
    久违的phpstorm
    软件项目版本号的命名规则及格式
    phpstudy 局域网访问
    java+eclipse+selenium环境搭建
    软件测试方法汇总
    功能测试大全
    如何有效地描述软件缺陷(Defect)?
  • 原文地址:https://www.cnblogs.com/person1-0-1/p/11556731.html
Copyright © 2011-2022 走看看