简体   繁体   中英

How do I call a Python function when something is logged

I'm using the logging library and I want to call a function whenever any event is logged. Something like this:

import logging

#logging config here

async def on_log(message, level): #call this whenever something is logged
    print(level, ":", message)

logging.debug("Hello world")

Edit: on_log is a coroutine

Edit2: I tried implementing one of your suggestions but I'm not 100% sure about how to add it to my current logging configuration.

from logging import *
import datetime
import sys

class MyLogger(Handler):
    def emit(*args):
        for item in args:
            print(item)

time = datetime.datetime.today()
logtime = f"{time.year}-{time.month}-{time.day}__{time.hour}h-{time.minute}m-{time.second}s"

file_handler = FileHandler(filename=f'./logs/{logtime}.log')  # File output
stdout_handler = StreamHandler(sys.stdout)  # Console output

basicConfig(
    format=f'[%(asctime)s][%(levelname)s] %(message)s',
    datefmt='%H:%M:%S',
    level=DEBUG,
    handlers=[file_handler, stdout_handler, MyLogger]
)

I get this error: AttributeError: type object 'MyLogger' has no attribute 'formatter'

It is minimal working code

import logging

# --- classes ---

class MyLogger():

    #level = logging.NOTSET
    level = logging.DEBUG

    def handle(*args):
        print('--- args ---')
        for item in args:
            print(item)
        print('---')

# --- main ---

logger = logging.getLogger('test')
logger.setLevel(logging.DEBUG) 
#logger.setLevel(logging.INFO) 

my_logger = MyLogger()
#my_logger.level = logging.DEBUG

logger.addHandler(my_logger)

# --- test ---

logger.debug("DEBUG: Hello world")
logger.info("INFO: Hello world")

It can't be function but class with method handle and in variable level because every handler has own level. This way some handlers can be executed always, other only for debug message.


EDIT:

The same using class Handler which already has variable level and you have to only rewrite method handle . But is better to rewrite method emit which is executed by handle after filtering.

You can set level when you create instance.

import logging

# --- classes ---

class MyLogger(logging.Handler):
    
    #def handle(*args):
    def emit(*args):
        print('--- args ---')
        for item in args:
            print(item)
        print('---')
        
# --- main ---

logger = logging.getLogger('test')
logger.setLevel(logging.DEBUG) 
#logger.setLevel(logging.INFO) 

my_logger = MyLogger(logging.DEBUG)

logger.addHandler(my_logger)

# --- test ---

logger.debug("DEBUG: Hello world")
logger.info("INFO: Hello world")

The comments recommend using a custom handler but I would advise against it since there is a way to do this that is also proposed in the official documentation by using filters. In the specific case here it would work like this:

import logging

def on_log(record):
    print(record.levelname, ":", record.getMessage())
    return True

logging.root.addFilter(on_log)

logging.warning('some log')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM