Python logging split between stdout and stderr [duplicate]
Asked Answered
S

2

38

Is it possible to have python logging messages which are INFO or DEBUG to go to stdout and WARNING or greater to go to stderr?

Sclerotomy answered 17/4, 2013 at 13:39 Comment(0)
S
74

This seems to do what I want:

#!/usr/bin/python
import sys
import logging


class InfoFilter(logging.Filter):
    def filter(self, rec):
        return rec.levelno in (logging.DEBUG, logging.INFO)


logger = logging.getLogger("__name__")
logger.setLevel(logging.DEBUG)

h1 = logging.StreamHandler(sys.stdout)
h1.setLevel(logging.DEBUG)
h1.addFilter(InfoFilter())
h2 = logging.StreamHandler()
h2.setLevel(logging.WARNING)

logger.addHandler(h1)
logger.addHandler(h2)
Sclerotomy answered 17/4, 2013 at 17:36 Comment(5)
Creating a filter class is actually not necessary. You can also pass a callable: h1.addFilter(lambda record: record.levelno <= logging.INFO)Exterminate
@Schiavini, for what it's worth, your modification doesn't seem to work in Python 2.7.15 - logging/__init__.py:Filterer.filter() raises an error: AttributeError: 'function' object has no attribute 'filter'. The code as-written does work in this version of Python.Coarctate
I've only tested with python 3. That probably means you'll need the class as mentioned in the answer.Exterminate
Side effect: consecutive log messages may get displayed in the wrong order (e.g. when combining stdout and stderr in the console). I guess this is due to the fact that both streams may use independent buffers. I couldn't find a way to fix this yet.Gloria
Typically, you would use logger = logging.getLogger(__name__) (without the quotation marks) to use the name of the module.Synergist
L
-2

I thought this would help: Handler.setLevel(lvl)

Sets the threshold for this handler to lvl. Logging messages which are less severe than lvl will be ignored. When a handler is created, the level is set to NOTSET (which causes all messages to be processed).

But now I see that it wouldn't do what you want (split INFO/DEBUG from WARNING/ERROR)

That being said, you could write a custom handler (a class extending logging.StreamHandler for example), and overwrite the Handler.handle() method.

Lezlie answered 17/4, 2013 at 13:45 Comment(3)
This is not enough to stop WARNING messages to be logged to stdout still.Intendancy
A filter would probably be better.Embrocation
Correct, I noticed it after posting my answer. Fixed now.Lezlie

© 2022 - 2024 — McMap. All rights reserved.