[Tutor] python logger
Peter Otten
__peter__ at web.de
Wed Dec 28 19:40:50 CET 2011
rail shafigulin wrote:
> has anyone used python logger before? i'm trying to adapt it for my
> workplace. right now it is pretty simplistic for me. i'm trying to
> generate
> extra output by the LoggerAdapter. however i'm getting errors.
> specifically i get the following message:
>
> Traceback (most recent call last):
> File "/usr/lib/python3.1/logging/__init__.py", line 770, in emit
> msg = self.format(record)
> File "/usr/lib/python3.1/logging/__init__.py", line 650, in format
> return fmt.format(record)
> File "/usr/lib/python3.1/logging/__init__.py", line 438, in format
> record.message = record.getMessage()
> File "/usr/lib/python3.1/logging/__init__.py", line 308, in getMessage
> msg = msg % self.args
> TypeError: not all arguments converted during string formatting
>
> i'm using
> this<http://docs.python.org/release/3.1.3/library/logging.html#using-
loggeradapters-to-impart-contextual-information>documentation.
> any
>
> here is my code
[snip]
That's not the actual code; it fails with another exception:
Traceback (most recent call last):
File "logger_orig.py", line 74, in <module>
main()
File "logger_orig.py", line 70, in main
mylogadapter = logger.LoggerAdapter(mylogger, testinfo)
NameError: global name 'logger' is not defined
In the actual code the line
> mylogadapter = logger.LoggerAdapter(mylogger, testinfo)
has probably logging instead of logger. Under that assumption:
Technically you get an error because you have a format string without any
placeholders. When the info() method of a Logger (or LoggerAdapter) receives
more than one argument it tries to use the first argument as a format string
as demonstrated below:
>>> import logging
>>> logging.basicConfig(level=logging.INFO)
>>> logging.info("foo")
INFO:root:foo
>>> logging.info("foo", "bar")
Traceback (most recent call last):
File "/usr/lib/python3.1/logging/__init__.py", line 770, in emit
msg = self.format(record)
File "/usr/lib/python3.1/logging/__init__.py", line 650, in format
return fmt.format(record)
File "/usr/lib/python3.1/logging/__init__.py", line 438, in format
record.message = record.getMessage()
File "/usr/lib/python3.1/logging/__init__.py", line 308, in getMessage
msg = msg % self.args
TypeError: not all arguments converted during string formatting
>>> logging.info("foo BAR:%s", "bar")
INFO:root:foo BAR:bar
>>> logging.info("foo BAR:%s BAZ:%s", "bar", "baz")
INFO:root:foo BAR:bar BAZ:baz
I've not used a LoggerAdapter myself, but as I read the docs it is meant to
simplify the addition of extra data, e. g. if you have
common_extra = {"notes": "whatever"}
...
logger.info("one", extra_common_extra)
...
logger.info("two", extra=common_extra)
...
logger.info("three", extra=common_extra)
...
you can simplify that to
logger = logging.LoggingAdapter(logger, {"notes": "whatever"})
...
logger.info("one")
...
logger.info("two")
...
logger.info("three")
Applying the principle to your code:
def main():
# recommended indent is 4 spaces
testinfo = TestInfo(
test_name='myname',
description='mydescription',
notes='mynotes',
expected='myexpected',
actual='myactual',
status='Fail',
timestamp='mystamp')
mylogger = logging.getLogger('mylogger')
mylogger.setLevel(logging.DEBUG)
filehandler = logging.FileHandler('test.log')
filehandler.setLevel(logging.DEBUG)
# added to verify that testinfo is indeed passed on:
formatter = logging.Formatter(logging.BASIC_FORMAT + " notes:
%(notes)s")
filehandler.setFormatter(formatter)
mylogger.addHandler(filehandler)
mylogadapter = logging.LoggerAdapter(mylogger, testinfo)
mylogadapter.info('this is a log message')
#without adapter the above line would be:
#mylogger.info('this is a log message', extra=testinfo)
if __name__ == "__main__":
main()
More information about the Tutor
mailing list