devork

E pur si muove

Warnings revisited (aka logging vs warnings)

Wednesday, November 22, 2006

Earlier I posted about how to make warning messages from warnings.warn() look like fairly normal messages so they don't give you all the details about which line of code called them. The result was neat, but I found it a fairly crude way of doing it.

There is another module that does something very similar for getting messages to the user, and even slightly more flexible, and it is called logging. Don't be deceived by it's name like I was, it can be used to just "log" onto the console too. It's even better as the default behaviour is very close to what a console application would need. Let me show the code to get this going:

import logging logging.basicConfig(format='%(levelname)s: %(message)s') logging.warn("Foo is warnging you about bar")

That's it, and it is a lot cleaner then doing this using the warnings module.

Leaves the question, which module to chose. I was wondering too, and a search on "warnings vs logging" only gives one real result. Luckily the explenation of Kristian Reis agrees with what my gut feeling has started to suppose:

warnings are for code `issues', log messages are for application level `issues', right?

I didn't find anyone answering that question, but at least I agree with it. So I reckon it is right...

Overriding formatting of warnings.warn()

Tuesday, November 14, 2006

Today I needed to add the printing of warning messages to a command line tool written in Python. So Instead of writing things out using print, wich is not flexible enough and goes against my way to avoid user interaction deep inside functions and classes, I decided to use the warnings module.

That was easy enough, just send a UserWarning, but I didn't like the way how the warning was printed, with line number and everything. So I had to find a way to make this nicer in this case. What I ended up with is this code in the beginning of the module:

# Overide the default format for warnings.
_formatwarningBackup = warnings.formatwarning
def _formatwarning(message, category, filename, lineno):
if category is UserWarning:
return 'WARNING: %s\n' % message
else:
return _formatwarningBackup(message, category, filename, lineno)
warnings.formatwarning = _formatwarning

It seems a little bit dirty, but I think it is an acceptable solution. If a module somwhere uses the wanrings mechanism for something it should still appear as normal, while my own warnings are masked nicely and conforming with the other output of the program.

As I couldn't find any examples of how to do this when searching, I have now provided one. ;-)

[Sorry about the fact that indentation seems to go all wonky in the code block]

Subscribe to: Posts (Atom)