13

For my first logging experiment in Python (2.7) I'm creating a basic logging module, which will quickly create a logger for (so I won't have to configure it per module/class).

What I want to do is to create a logger which displays all messages of level INFO and higher on the console, and moves all DEBUG level information to a text file.

Thus far I have create a logger which prints INFO and up to the console, and which prints every log messages to a text file. However, I don't want all the INFO and higher messages in my text file.

I have made a Python Fiddle which holds my code.

I used the following debug messages from a tutorial:

log.debug('All systems operational')
log.info('Airspeed 300 knots')
log.warn('Low on fuel')
log.error('No fuel. Trying to glide.')
log.critical('Glide attempt failed. About to crash.')

Which on the console produce:

[INFO] root: Airspeed 300 knots
[WARNING] root: Low on fuel
[ERROR] root: No fuel. Trying to glide.
[CRITICAL] root: Glide attempt failed. About to crash.

And in my debug_log.txt file:

2013-06-14 14:51:46,963:DEBUG:root:All systems operational
2013-06-14 14:51:46,964:INFO:root:Airspeed 300 knots
2013-06-14 14:51:46,964:WARNING:root:Low on fuel
2013-06-14 14:51:46,964:ERROR:root:No fuel. Trying to glide.
2013-06-14 14:51:46,964:CRITICAL:root:Glide attempt failed. About to crash.

In the above block, the latter four lines should not be in the file. Is what I'm trying to do possible and how would I get the desired result?

Marijke Luttekes
  • 1,253
  • 1
  • 12
  • 27

1 Answers1

17

You have to create your own handler object.

From the documentation: The FileHandler class, located in the core logging package, sends logging output to a disk file. It inherits the output functionality from StreamHandler. So here the idea is to extend the FileHandler class, and in the emit() method, filter out all record objects that are not in the logging.DEBUG level.

I have not tested this, but I think it would do the job:

from logging import FileHandler, DEBUG

log = logging.getLogger('foo')


class DebugFileHandler(FileHandler):
    def __init__(self, filename, mode='a', encoding=None, delay=False)
        super().__init__(filename, mode, encoding, delay)
    
    def emit(self, record):
        if not record.levelno == DEBUG:
            return
        super().emit(record)

log.addHandler(DebugFileHandler())

Of course, you'll have to adapt this code to your code. And, to be honest, record.level is a wild guess, but I think it makes sense :-) And, I got it right!

In this example, the handler will only be applied for the foo logger. You may want to activate it for your main handler, or only for some specific handlers, as you may prefer.

Marius Retegan
  • 2,416
  • 1
  • 17
  • 12
zmo
  • 24,463
  • 4
  • 54
  • 90
  • 1
    Here, I was just writing it out :-) – zmo Jun 14 '13 at 13:44
  • 1
    Thank you, I'll have to look what code works exactly, but with this information I'll get there. :) – Marijke Luttekes Jun 14 '13 at 13:44
  • 1
    For future references I think it's nice to point out the following: The above code works mostly. There are some colons missing at the end of the class, but those are easy to spot. If you replace the line `if record.level != DEBUG:` with `if not record.levelno == DEBUG:`, all non-DEBUG logs are filtered out nicely. – Marijke Luttekes Jun 15 '13 at 14:50
  • indeed, I misread the documentation, thank you for spotting it, I'm updating my answer – zmo Jun 15 '13 at 17:26
  • 1
    Wouldn't it be more appropriate to create a [filter object](http://docs.python.org/2/library/logging.html#filter-objects) and attach it to the handler? – glglgl Nov 28 '13 at 14:11
  • 1
    indeed, that would work out, though I don't think this is appropriate. As a general rule, simpler is better, and you anyway need a `FileHandler` to do the job, so there's no need to add another instance to handle that. And as the documentation you've linked states: `Although filters are used primarily to filter records based on more sophisticated criteria than levels [...]`, i.e. it can do it, but it's been design for more than *just* that. – zmo Dec 02 '13 at 21:10
  • Hello, @zmo would you care to answer this question related to this problem? https://stackoverflow.com/q/67460075/12415287 – Prosy Arceno May 09 '21 at 20:58