开发者

Extending the Python Logger

I'm looking for a simple way to extend the logging functionality defined in the standard python library. I just want the ability to ch开发者_开发问答oose whether or not my logs are also printed to the screen.

Example: Normally to log a warning you would call:

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s: %(message)s', filename='log.log', filemode='w')
logging.warning("WARNING!!!")

This sets the configurations of the log and puts the warning into the log

I would like to have something along the lines of a call like:

logging.warning("WARNING!!!", True)

where the True statement signifys if the log is also printed to stdout.

I've seen some examples of implementations of overriding the logger class

but I am new to the language and don't really follow what is going on, or how to implement this idea. Any help would be greatly appreciated :)


The Python logging module defines these classes:

Loggers that emit log messages.
Handlers that put those messages to a destination.
Formatters that format log messages.
Filters that filter log messages.

A Logger can have Handlers. You add them by invoking the addHandler() method. A Handler can have Filters and Formatters. You similarly add them by invoking the addFilter() and setFormatter() methods, respectively.

It works like this:

import logging

# make a logger
main_logger = logging.getLogger("my logger")
main_logger.setLevel(logging.INFO)

# make some handlers
console_handler = logging.StreamHandler() # by default, sys.stderr
file_handler    = logging.FileHandler("my_log_file.txt")

# set logging levels
console_handler.setLevel(logging.WARNING)
file_handler.setLevel(logging.INFO)

# add handlers to logger
main_logger.addHandler(console_handler)
main_logger.addHandler(file_handler)

Now, you can use this object like this:

main_logger.info("logged in the FILE")
main_logger.warning("logged in the FILE and on the CONSOLE")

If you just run python on your machine, you can type the above code into the interactive console and you should see the output. The log file will get crated in your current directory, if you have permissions to create files in it.

I hope this helps!


It is possible to override logging.getLoggerClass() to add new functionality to loggers. I wrote simple class which prints green messages in stdout.

Most important parts of my code:

class ColorLogger(logging.getLoggerClass()):
    __GREEN = '\033[0;32m%s\033[0m'
    __FORMAT = {
        'fmt': '%(asctime)s %(levelname)s: %(message)s',
        'datefmt': '%Y-%m-%d %H:%M:%S',
    }

    def __init__(self, format=__FORMAT):
        formatter = logging.Formatter(**format)

        self.root.setLevel(logging.INFO)
        self.root.handlers = []

        (...)

        handler = logging.StreamHandler()
        handler.setFormatter(formatter)
        self.root.addHandler(handler)

    def info(self, message):
        self.root.info(message)

    (...)

    def info_green(self, message):
        self.root.info(self.__GREEN, message)

(...)

if __name__ == '__main__':
    logger = ColorLogger()
    logger.info("This message has default color.")
    logger.info_green("This message is green.")


Handlers send the log records (created by loggers) to the appropriate destination.

(from the docs: http://docs.python.org/library/logging.html)

Just set up multiple handlers with your logging object, one to write to file, another to write to the screen.

UPDATE

Here is an example function you can call in your classes to get logging set up with a handler.

def set_up_logger(self):
    # create logger object
    self.log = logging.getLogger("command")
    self.log.setLevel(logging.DEBUG)

    # create console handler and set min level recorded to debug messages
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)

    # add the handler to the log object        
    self.log.addHandler(ch)

You would just need to set up another handler for files, ala the StreamHandler code that's already there, and add it to the logging object. The line that says ch.setLevel(logging.DEBUG) means that this particular handler will take logging messages that are DEBUG or higher. You'll likely want to set yours to WARNING or higher, since you only want the more important things to go to the console. So, your logging would work like this:

self.log.info("Hello, World!") -> goes to file
self.log.error("OMG!!") -> goes to file AND console
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜