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?
Asked
Active
Viewed 2.9k times
2 Answers
68
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)

Martin Thoma
- 124,992
- 159
- 614
- 958

crosswired
- 1,351
- 2
- 11
- 12
-
27Creating a filter class is actually not necessary. You can also pass a callable: `h1.addFilter(lambda record: record.levelno <= logging.INFO)` – Schiavini Mar 13 '18 at 10:43
-
@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. – davidA Apr 28 '19 at 23:54
-
1I've only tested with python 3. That probably means you'll need the class as mentioned in the answer. – Schiavini Apr 29 '19 at 14:17
-
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. – Johnson_145 Sep 24 '20 at 22:27
-
2Typically, you would use `logger = logging.getLogger(__name__)` (without the quotation marks) to use the name of the module. – Tom Pohl Mar 31 '22 at 13:11
-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.

E.Z.
- 6,393
- 11
- 42
- 69
-
This is not enough to *stop* WARNING messages to be logged to stdout *still*. – Martijn Pieters Apr 17 '13 at 13:48
-
1
-