Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use python logging to log bytes to one handler, and unicode to another?

I have a complex (but fairly standard) log setup in my python3 application. A single log function is used, and then various handlers distribute those logs to different places, such as console output, a log file, and a hardware serial port. This had been working fine in python2, but I'm converting to python3 and starting to hit an issue. The console and file output handlers are expecting unicode, but the StreamHandler that handles the serial output requires bytes encoding. I don't see any way to tell python to convert to bytes just for a single log handler.

Here is some partial code for reference:

serial_handler = logging.StreamHandler(serial)
serial_handler.setLevel(logging.DEBUG)
serial_handler.setFormatter(serial_formatter)
self._log.addHandler(serial_handler)

fh = logging.FileHandler(file_name)
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
self._log.addHandler(fh)

Then self._log.debug("Hello, world!") could be called. But it's going to send unicode to the FileHandler, which is correct, but also to the StreamHandler, which will fail because it needs to be encoded to bytes after the logging.Formatter function has occurred, and I don't know how to make that happen.

Note serial in this case is an instance of the pySerial class. It's .write() function expects bytes.

like image 386
Dave Avatar asked Sep 05 '25 03:09

Dave


1 Answers

I ended up writing a custom Handler which seems to be working. But I'm still curious to see proposed alternatives.

from logging import StreamHandler

class SerialHandler(StreamHandler):

    def __init__(self, serial):
        StreamHandler.__init__(self, serial)

    def emit(self, record):
        try:
            msg = self.format(record)
            stream = self.stream
            stream.write(bytes(msg + self.terminator, 'utf-8'))
            self.flush()
        except RecursionError:
            raise
        except Exception:
            self.handleError(record)
like image 120
Dave Avatar answered Sep 07 '25 17:09

Dave