6

Is there a way to dynamically set which log level I want a statement logged as?

I have this code:

logging.info("Data Set Size => {0}".format(len(data)))
logging.info("Training Set Size => {0}".format(len(train)))
logging.info("Test Set Size => {0}".format(len(test)))
logging.info("Entire data set allocated => {0}".format(len(data) == len(train) + len(test)))

It very nicely outputs something similar to this, depending on the format I've set:

root        : INFO     Data Set Size => 10000
root        : INFO     Training Set Size => 7500
root        : INFO     Test Set Size => 2500
root        : INFO     Entire data set allocated => True

Now, the question I have, if the logic check in that last line is False, can I set that level to a .warning?

I could do something like this:

if len(data) == len(train) + len(test):
    logging.info("Entire data set allocated => {0}".format(True)
else:
    logging.warning("Entire data set allocated => {0}".format(False)

But, is there a way to do it in fewer lines?

1
  • Use %s style formatting with loggers, passing values as arguments. This is because the logging module supports it, strings wont be formatted unless the msg is emitted. Commented Dec 3, 2014 at 4:57

3 Answers 3

8

Use Logger.log() instead of the functions named after levels; this takes a level as the first argument:

entire_set = len(data) == len(train) + len(test)
logging.log(logging.WARNING if entire_set else logging.INFO,
            "Entire data set allocated => {0}".format(entire_set))

The logging.warning() and logging.info() functions are merely shortcuts for calling logging.log() with a given log level.

You probably want to switch to using a dedicated Logger object rather than use the module-level functions; it'll allow you to configure logging more granularly and track where log messages came from by their logger name.

Sign up to request clarification or add additional context in comments.

3 Comments

Since warning and info are shortcuts, that means I can keep those statements in place for the first three lines I'm logging and just modify the last line, correct? I don't need to switch everything to use logging.log()?
Right, but you have just put the conditional statement in one line :-) And you could also remove the .format(False).
@NewGuy: yes, use the shortcuts where you can, use logging.log() when you need to use a dynamic level.
1

You need to implement a conditional switch. Meaning: you need an if/else clause. With an if/else clause being required, there is no way to make it "shorter" than you have it. The only way to make this significantly shorter is that you come up with an approach that does not need to distinguish two cases.

And then I need to ask: why would you want to have this in shorter code? The code you propose is perfectly readable.

In your current proposal, you should remove the .format(True) and .format(False) fragments (the result is constant and known, so you can hardcode it). That however does not really shorten your code.

Comments

-2

If you want all following info loggings into warning loggings you could replace the info function by the warning function as shown:

if len(data) == len(train) + len(test):
    pass
else:
    logging.info = logging.warning

So you don't need to do this test when with every followed logging.info statement. If this is useful for you depends on the rest of the logging code of course.

I don't quite understand why you want to increase the logging level of a statement. Usually one does the reverse. If one critical condition fails one increases the loglevel with

logging.setLevel

and all logging statements with no info level have the warning level. Since the info statements are included in the logging, there is usually no need of increasing the level of the statement itself.

4 Comments

Don't use if ...: pass, else: when you can use if len(data) != len(train) + len(test) instead. Altering the method binding is a terrible idea however.
I don't want to change all future info messages to warnings, just the single statement.
If :pass was just along the lines of his statements. There is no need fo downvoting this. But since this is SO.... anyways, method binding can be very useful, this heavily depends on his code.
Not in this case; at best I'd use log = logging.info or log = logging.warning to store this as a local variable.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.