8

Let's say I got this logging.logger instance:

import logging logger = logging.getLogger('root') FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s" logging.basicConfig(format=FORMAT) logger.setLevel(logging.DEBUG) 

Problem comes when I try to use it like the builtin print with a dynamic number of arguments:

>>> logger.__class__ <class 'logging.Logger'> >>> logger.debug("hello") [<stdin>:1 - <module>() ] hello >>> logger.debug("hello","world") Traceback (most recent call last): File "c:\Python2711\Lib\logging\__init__.py", line 853, in emit msg = self.format(record) File "c:\Python2711\Lib\logging\__init__.py", line 726, in format return fmt.format(record) File "c:\Python2711\Lib\logging\__init__.py", line 465, in format record.message = record.getMessage() File "c:\Python2711\Lib\logging\__init__.py", line 329, in getMessage msg = msg % self.args TypeError: not all arguments converted during string formatting Logged from file <stdin>, line 1 

How could i emulate the print behaviour still using logging.Logger?

2
  • 1
    just enclose params in brackets like logger.debug(("hello","world")) for example Commented Sep 19, 2016 at 8:55
  • Andrey: Mmm, ok, I can make a fast search&replace from all my prints following your pattern, cheers ;-) Commented Sep 19, 2016 at 9:00

3 Answers 3

2

Wrapper based on @Jim's original answer:

import logging import sys _logger = logging.getLogger('root') FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s" logging.basicConfig(format=FORMAT) _logger.setLevel(logging.DEBUG) class LogWrapper(): def __init__(self, logger): self.logger = logger def info(self, *args, sep=' '): self.logger.info(sep.join("{}".format(a) for a in args)) def debug(self, *args, sep=' '): self.logger.debug(sep.join("{}".format(a) for a in args)) def warning(self, *args, sep=' '): self.logger.warning(sep.join("{}".format(a) for a in args)) def error(self, *args, sep=' '): self.logger.error(sep.join("{}".format(a) for a in args)) def critical(self, *args, sep=' '): self.logger.critical(sep.join("{}".format(a) for a in args)) def exception(self, *args, sep=' '): self.logger.exception(sep.join("{}".format(a) for a in args)) def log(self, *args, sep=' '): self.logger.log(sep.join("{}".format(a) for a in args)) logger = LogWrapper(_logger) 
Sign up to request clarification or add additional context in comments.

2 Comments

In this way, the %lineno will always be the one in LogWrapper, which might be unwanted.
dont forget to add **kwargs to all functions
1

Alternatively, define a function that accepts *args and then join them in your call to logger:

def log(*args, logtype='debug', sep=' '): getattr(logger, logtype)(sep.join(str(a) for a in args)) 

I added a logtype for flexibility here but you could remove it if not required.

2 Comments

Excellent! I've added my answer based on your code, thanks ;)
... "{}".format(a) is really just an ugly and convoluted way of writing str(a)... Also (f(x) for x in sequence) is just map(f, sequence) if you like functional style.
-1

Set sys.stdout as the stream for your logging.

e.g. logging.basicConfig(level=logging.INFO, stream=sys.stdout)

2 Comments

I've tried it out with python 3.5.1 and that still crashes TypeError: not all arguments converted during string formatting
If had that happen before to me, the line that caused it did something like: ('{} {}', variable1, variable2). When changed to '{} {}'.format(variable1, variable2) fixed it for me.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.