2

I have the following logging set up:

import logging
logging.basicConfig(level=logging.DEBUG,
                format='[%(asctime)s] - %(funcName)s - %(message)s',
                datefmt='%a, %d %b %Y %H:%M:%S',
                filename='/tmp/affiliate.log',
                filemode='w')

How would I convert the following two statements -- which writes to the log file and then prints the output:

logging.debug('>>>>> 401 Error: Cannot download file')
print '>>>>> 401 Error: Cannot download file'

Into one logging statement that does both?

David542
  • 104,438
  • 178
  • 489
  • 842
  • 3
    Register both a `FileHandler` and `StreamHandler` for your logger. See [this answer](http://stackoverflow.com/a/11327339/1599111) for an example. – Lukas Graf Sep 17 '14 at 17:54
  • A very simple solution that works in Python 2 as well as 3 is shown in [this answer](http://stackoverflow.com/a/23681578/544059). – metakermit May 22 '15 at 13:05
  • possible duplicate of [Python using basicConfig method to log to console and file](http://stackoverflow.com/questions/13479295/python-using-basicconfig-method-to-log-to-console-and-file) – metakermit May 22 '15 at 13:07
  • it is not a duplicate. @kartheek posted Python 2 solution to Python 3 question by mistake ([the question](http://stackoverflow.com/q/13479295/4279) should have had `python-3.x` tag, though it might be too late to add it) – jfs May 24 '15 at 17:19

1 Answers1

7

You can't do it with just basicConfig (at least not in Python 2.7; 3.3 added new features, in particular the handlers parameter), but it's easy to set up the logger to write to two places. The Logging Cookbook explains how to do all kinds of things in full detail.

A few of the cookbook entries aren't fully explained, just demonstrated, but you can always look up the details in the logging docs.

The key thing you're looking for here is to create two handlers — a FileHandler('/tmp/affiliate.log'), and a StreamHandler(sys.stdout).

If you want the same format, log level, etc. in both the log file and stdout, one of the early examples in the cookbook does exactly this, except with stderr. If you want different formats for each, the very next example does that.

So, instead of this:

logging.basicConfig(level=logging.DEBUG,
                format='[%(asctime)s] - %(funcName)s - %(message)s',
                datefmt='%a, %d %b %Y %H:%M:%S',
                filename='/tmp/affiliate.log',
                filemode='w')

Do this:

logger = logging.getLogger('')
logger.setLevel(logging.DEBUG)
fh = logging.FileHandler('/tmp/affiliate.log')
sh = logging.StreamHandler(sys.stdout)
formatter = logging.Formatter('[%(asctime)s] - %(funcName)s - %(message)s',
                               datefmt='%a, %d %b %Y %H:%M:%S')
fh.setFormatter(formatter)
sh.setFormatter(formatter)
logger.addHandler(fh)
logger.addHandler(sh)

Note that the second example I linked uses basicConfig to do everything it can do, then adds a second handler on top of it. I think this is a little less clear, but if you want to do the same, you can do it.

Community
  • 1
  • 1
abarnert
  • 354,177
  • 51
  • 601
  • 671
  • 1
    You can do it with just `basicConfig()` in Python 3.3+ via `handlers` parameter. – jfs May 24 '15 at 17:15
  • @J.F.Sebastian Good point. The OP is clearly using 2.x, but for future searchers that's worth mentioning. – abarnert May 24 '15 at 17:19