How to get the current log level in python logging module
Asked Answered
S

5

54

I'm trying to create a basic logger that will be colored without external packages,

# these have to be the first functions so I can use it in the logger settings
def create_log_name(log_path="{}/log", filename="zeus-log-{}.log"):
    if not os.path.exists(log_path.format(os.getcwd())):
        os.mkdir(log_path.format(os.getcwd()))
    find_file_amount = len(os.listdir(log_path.format(os.getcwd())))
    full_log_path = "{}/{}".format(log_path.format(os.getcwd()), filename.format(find_file_amount + 1))
    return full_log_path


def set_color_value(levelname):
    log_set = {
        "INFO": "\033[92m{}\033[0m",
        "WARNING": "\033[93m{}\033[0m",
        "DEBUG": "\033[94m{}\033[0m",
        "ERROR": "\033[91m{}\033[0m",
        "CRITICAL": "\033[91m{}\033[0m"
    }
    return log_set[levelname].format(levelname)

logger = logging.getLogger("zeus-log")
logger.setLevel(logging.DEBUG)
file_handler = logging.FileHandler(
    filename=create_log_name(), mode="a+"
)
file_handler.setLevel(logging.DEBUG)
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
file_format = logging.Formatter(
    '%(asctime)s;%(name)s;%(levelname)s;%(message)s'
)
console_format = logging.Formatter(
    "[%(asctime)s {}] %(message)s".format(set_color_value()), "%H:%M:%S"
)
file_handler.setFormatter(file_format)
console_handler.setFormatter(console_format)
logger.addHandler(console_handler)
logger.addHandler(file_handler)

So as of right now, all I need to do is get the current log level that will be set in the logging.Formatter and send it to my little function:

console_format = logging.Formatter(
    "[%(asctime)s {}] %(message)s".format(set_color_value()), "%H:%M:%S"
)

Is it possible to get the current log level from the logging package?


For example, lets say I pass logger.INFO("test") I need a way to get that INFO part in as a string, from there, set_color_value("INFO") should return:

enter image description here

Sorn answered 28/8, 2017 at 16:14 Comment(0)
S
8

I decided to do this a different way and add color through the string itself with a level number:

def set_color(org_string, level=None):
    color_levels = {
        10: "\033[36m{}\033[0m",       # DEBUG
        20: "\033[32m{}\033[0m",       # INFO
        30: "\033[33m{}\033[0m",       # WARNING
        40: "\033[31m{}\033[0m",       # ERROR
        50: "\033[7;31;31m{}\033[0m"   # FATAL/CRITICAL/EXCEPTION
    }
    if level is None:
        return color_levels[20].format(org_string)
    else:
        return color_levels[int(level)].format(org_string)

So for example:

logger.info(set_color("test"))
logger.debug(set_color("test", level=10))
logger.warning(set_color("test", level=30))
logger.error(set_color("test", level=40))
logger.fatal(set_color("test", level=50))

Will output:

enter image description here

Sorn answered 28/8, 2017 at 17:13 Comment(1)
You can also replace the default logging.Formatter with ColorFormatter subclass that has format method ``` COLOR_MAP = { DEBUG : 'white', <...> ERROR : 'red', } def format(self, record): msg = logging.Formatter.format(self, record) # Now set color based on our level, if mapped. Else leave as is if record.levelno in ColorFormatter.COLOR_MAP: msg = termcolor.colored(msg, ColorFormatter.COLOR_MAP[record.levelno]) return msg ```Inversely
G
57

If you're using the root logger, for example because you called logging.basicConfig() then you can use

import logging
logging.root.level

For example

if logging.DEBUG >= logging.root.level:
    # Do something
Ganda answered 27/12, 2018 at 22:56 Comment(1)
It is better to use the isEnabledFor() function instead of an explicit comparision. See here: docs.python.org/3/howto/logging.html#optimizationHomely
D
34

Yes, you can check the logger level by

level = logger.level
Daradarach answered 28/8, 2017 at 16:18 Comment(6)
Doesn't this just show the level that the current logger is set to? I need a way to get the logging information from each string passed from the logger, for example, lets say that I pass logger.FATAL("test") I need that FATAL part passed as a stringSorn
This answer answers what the question asked. Your question needs improvement since I arrived here looking for this answer.Adder
Agreed. The content of your question is at odds with the title of your question, @wahwahwah. The latter is likely of more interest to StackOverflowers (including myself). It is oddly non-orthogonal that the logging API defines setLevel() and getEffectiveLevel() methods but no getLevel() method, when they could have simply defined a trivial getLevel(self): return self.level method. </sigh>Bremen
Whether I set this to INFO or DEBUG e.g. like this logging.basicConfig(stream=sys.stdout, level='DEBUG') the logger.level always shows me 0, not helpful. @CecilCurry What does "oddly non-orthogonal" mean? In the context of this definition of orthogonality I am not sureCoequal
@CecilCurry Seconding your opinion. The documentation page of logging doesn't mention level could be directly accessed through the logger object. It only mentions getEffectiveLevel as the way to get the current log level. Nothing else could be found to achieve the same purpose.Athens
This really should be logger.getEffectiveLevel() since if the logger.level = 0 then it will retrieve the logging.root.level which is 30 by default (if it hasn't been modified). And therefore logger.getEffectiveLevel() != logger.levelBahamas
C
26

As explained in this walk through the source code logger.level is often wrong.

You want logger.getEffectiveLevel()

To quote the source:

Here’s the takeaway: don’t rely on .level. If you haven’t explicitly set a level on your logger object, and you’re depending on .level for some reason, then your logging setup will likely behave differently than you expected it to.

Catwalk answered 16/6, 2021 at 20:30 Comment(0)
S
10

In your logger instance you can check it like this, as @Milán Vásárhelyi said:

myLogger.level

That will return the level as int. if you prefer to show the name, as string, you can do:

logging.getLevelName(myLogger.level)

Sippet answered 26/11, 2020 at 9:56 Comment(0)
S
8

I decided to do this a different way and add color through the string itself with a level number:

def set_color(org_string, level=None):
    color_levels = {
        10: "\033[36m{}\033[0m",       # DEBUG
        20: "\033[32m{}\033[0m",       # INFO
        30: "\033[33m{}\033[0m",       # WARNING
        40: "\033[31m{}\033[0m",       # ERROR
        50: "\033[7;31;31m{}\033[0m"   # FATAL/CRITICAL/EXCEPTION
    }
    if level is None:
        return color_levels[20].format(org_string)
    else:
        return color_levels[int(level)].format(org_string)

So for example:

logger.info(set_color("test"))
logger.debug(set_color("test", level=10))
logger.warning(set_color("test", level=30))
logger.error(set_color("test", level=40))
logger.fatal(set_color("test", level=50))

Will output:

enter image description here

Sorn answered 28/8, 2017 at 17:13 Comment(1)
You can also replace the default logging.Formatter with ColorFormatter subclass that has format method ``` COLOR_MAP = { DEBUG : 'white', <...> ERROR : 'red', } def format(self, record): msg = logging.Formatter.format(self, record) # Now set color based on our level, if mapped. Else leave as is if record.levelno in ColorFormatter.COLOR_MAP: msg = termcolor.colored(msg, ColorFormatter.COLOR_MAP[record.levelno]) return msg ```Inversely

© 2022 - 2024 — McMap. All rights reserved.