如何将python日志保存在不同级别的不同文件中

时间:2017-11-08 12:12:13

标签: python logging flask

我的日志代码:

import os
import logging
import logging.handlers
import sys
from logging import raiseExceptions
from logging import Logger

LOG_PATH = '/tmp/'


class AppLogger(Logger):

    def __init__(self, name, level=logging.NOTSET):
        super(AppLogger, self).__init__(name, level)

    def callHandlers(self, record):
        """
        Pass a record to all relevant handlers.

        Loop through all handlers for this logger and its parents in the
    logger hierarchy. If no handler was found, output a one-off error
        message to sys.stderr. Stop searching up the hierarchy whenever a
        logger with the "propagate" attribute set to zero is found - that
        will be the last logger whose handlers are called.
        """
        c = self
        found = 0
        while c:
            for hdlr in c.handlers:
                found = found + 1
                if hdlr.name == 'console':
                    if record.levelno >= hdlr.level:
                        hdlr.handle(record)
                else:
                    if record.levelno == hdlr.level:
                        hdlr.handle(record)
            if not c.propagate:
                c = None  # break out
            else:
                c = c.parent
        if (found == 0) and raiseExceptions and not self.manager.emittedNoHandlerWarning:
            sys.stderr.write("No handlers could be found for logger"
                             " \"%s\"\n" % self.name)
            self.manager.emittedNoHandlerWarning = 1


def get_logger(logfile_name=__name__, log_path=LOG_PATH):
    '''save log to diffrent file by different log level into the log path
and print all log in console'''
    logging.setLoggerClass(AppLogger)
    formatter = logging.Formatter(
        '%(asctime)s %(name)s %(levelname)s %(message)s',
        '%Y-%m-%d %H:%M:%S')

    log_files = {
        logging.DEBUG: os.path.join(log_path, logfile_name + '-debug.log'),
    logging.INFO: os.path.join(log_path, logfile_name + '-info.log'),
        logging.WARNING: os.path.join(log_path, logfile_name + '-warning.log'),
        logging.ERROR: os.path.join(log_path, logfile_name + '-error.log'),
        logging.CRITICAL: os.path.join(log_path, logfile_name + '-critical.log')
    }
    logger = logging.getLogger()
    logger.name = 'app'
    logger.setLevel(logging.DEBUG)
    for log_level, log_file in log_files.items():
        file_handler = logging.handlers.TimedRotatingFileHandler(log_file, 'midnight')
        file_handler.setLevel(log_level)
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)

    console_handler = logging.StreamHandler()
    console_handler.name = "console"
    console_handler.setLevel(logging.DEBUG)
    console_handler.setFormatter(formatter)
    logger.addHandler(console_handler)
    return logger


logger = get_logger()

我的烧瓶代码:

from log import logger

from flask import Flask
app = Flask(__name__)
app.debug = True


@app.route("/")
def hello():
    return "Hello World!"

logger.debug('----')
logger.info('----')
logger.error('----')
logger.warning('----')
app.run()

我想将debug.log中的DEBUG级别日志,info.log中的INFO级别日志,warning.log中的WARNING级别日志,error.log中的ERROR级别日志,以及烧瓶框架的日志和我的自定义日志,我需要打印所有登录控制台。

我自定义AppLogger,但现在这只是在烧瓶框架的日志上工作,我的自定义日志没有保存在正确的文件中,信息,警告,错误都写在info.log中,名称为{{ 1}}是我的自定义日志,它将日志保存在一起。

如何使info.log保存应用程序的INFO日志?

info.log:

app

warning.log

2017-11-08 20:07:31 app INFO ----
2017-11-08 20:07:31 app ERROR ----
2017-11-08 20:07:31 app WARNING ----
2017-11-08 20:07:31 werkzeug INFO  * Restarting with stat
2017-11-08 20:07:31 app INFO ----
2017-11-08 20:07:31 app ERROR ----
2017-11-08 20:07:31 app WARNING ----
2017-11-08 20:07:31 werkzeug INFO  * Debugger PIN: 971-444-041
2017-11-08 20:07:31 werkzeug INFO  * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

2 个答案:

答案 0 :(得分:0)

您只需为每个日志处理程序添加文件名 通过从

获取想法来更改您的代码
import logging

class MultiFileHandler(logging.FileHandler):

    def __init__(self, filename, mode, encoding=None, delay=0):
        logging.FileHandler.__init__(self, filename, mode, encoding, delay)

    def emit(self, record):
        if self.should_change_file(record):
            self.change_file(record.file_id)
        logging.FileHandler.emit(self, record)

    def should_change_file(self, record):
        if not hasattr(record, 'file_id') or record.file_id == self.baseFilename:
             return False
        return True

    def change_file(self, file_id):
        self.stream.close()

        self.baseFilename = file_id
        self.stream = self._open()

if __name__ == '__main__':

    logger = logging.getLogger('request_logger')
    logger.setLevel(logging.DEBUG)    
    handler = MultiFileHandler(filename='out.log', mode='a')
    handler.setLevel(logging.DEBUG)    
    logger.addHandler(handler)

    # Log some messages to the original file
    logger.debug('debug message')
    logger.info('info message')

    # Log some messages to a different file
    logger.debug('debug message',       extra={'file_id':'debug.log'})
    logger.info('info message',         extra={'file_id':'info.log'})
    logger.warn('warn message',         extra={'file_id':'warn.log'})
    logger.error('error message',       extra={'file_id':'error.log'})

答案 1 :(得分:0)

您可以创建一个过滤器:

import logging

class LevelFilter(object):

    def __init__(self, level):
        self.level = logging._checkLevel(level)

    def filter(self, record):
        return record.levelno == self.level

然后将其与每个文件关联:

(在YAML中):

handlers:
  info_handler:
    class: logging.handlers.RotatingFileHandler
    filename: /tmp/info.log
    ...
    filters: [info_filter]
  error_handler:
    class: logging.handlers.RotatingFileHandler
    filename: /tmp/errors.log
    ...
    filters: [err_filter]

filters:
  info_filter:
    (): <somelogclassmodule>.LevelFilter
    level: INFO
  err_filter:
    (): <somelogclassmodule>.LevelFilter
    level: ERROR

root:
  handlers: [info_handler, error_handler]

(在原始python中):

from <somelogclassmodule> import LevelFilter

root = logging.getLogger()

info_handler = logging.handlers.RotatingFileHandler('info.log', ...)
error_handler = logging.handlers.RotatingFileHandler('error.log', ...)

info_filter = LevelFilter('INFO')
err_filter = LevelFilter('ERROR')

info_handler.addFilter(info_filter)
error_handler.addFilter(err_filter)

# set formatters, etc..
...

root.addHandler(info_handler)
root.addHandler(error_handler)