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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With