When I first learned Python, I got used to doing this:
print "text", lineNumber, "some dictionary", my_dict
When I wrote my own logging facility, I naturally wanted to be able to hand it an arbitrarily-sized list of items, so I did this:
def error(*args):
print ERR_PREFIX,
for _x in args:
print _x,
print "\r\n",
error("text", lineNumber, "some dictionary", my_dict)
Now I want to start using the logging package because it has a lot more goodies and I don't feel like replicating their effort. Overall it looks like a clean design that can do a lot. But I'm stymied by the fact that you can no longer present it with the same list of items for it to print. Instead, I must change all my calls to something more like this:
error("text %d some dictionary %s" % (lineNumber, my_dict))
Or, I could do something really silly like this:
error(' '.join(map, str(("text", lineNumber, "some dictionary", my_dict))))
The question is, why omit such an obvious usage case? If you want to go from the typical 'print' statement straight to the new-fangled logging facility, shouldn't this be easier?
As a follow-up question, can you think of a way to override the Logger class to perform this?
I would suggest that it would be better to update the existing logging messages to the style that the logging module expects as it will be easier for other people looking at your code as the logging module will not longer function as they expect.
That out of the way, the following code will make the logging module behave as you desire.
import logging
import types
class ExtendedLogRecord(logging.LogRecord):
def getMessage(self):
"""
Return the message for this LogRecord.
Return the message for this LogRecord after merging any user-supplied
arguments with the message.
"""
if not hasattr(types, "UnicodeType"): #if no unicode support...
msg = str(self.msg)
else:
try:
msg = str(self.msg)
except UnicodeError:
msg = self.msg #Defer encoding till later
if self.args:
msg +=' '+' '.join(map(str,self.args))
return msg
#Patch the logging default logging class
logging.RootLogger.makeRecord=lambda self,*args: ExtendedLogRecord(*args)
some_dict={'foo':14,'bar':15}
logging.error('text',15,'some dictionary',some_dict)
Output:
ERROR:root:text 15 some dictionary {'foo': 14, 'bar': 15}
Patching the logging package (as one answer recommended) is actually a bad idea, because it means that other code (that you didn't write, e.g. stuff in the standard library) that calls logging.error() would no longer work correctly.
Instead, you can change your existing error() function to call logging.error() instead or print:
def error(*args):
logging.error('%s', ' '.join(map(str, args)))
(If there might be unicode objects you'd have to be a bit more careful, but you get the idea.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With