Search code examples
pythonloggingunicodepython-logging

UTF-8 In Python logging, how?


I'm trying to log a UTF-8 encoded string to a file using Python's logging package. As a toy example:

import logging

def logging_test():
    handler = logging.FileHandler("/home/ted/logfile.txt", "w",
                                  encoding = "UTF-8")
    formatter = logging.Formatter("%(message)s")
    handler.setFormatter(formatter)
    root_logger = logging.getLogger()
    root_logger.addHandler(handler)
    root_logger.setLevel(logging.INFO)

    # This is an o with a hat on it.
    byte_string = '\xc3\xb4'
    unicode_string = unicode("\xc3\xb4", "utf-8")

    print "printed unicode object: %s" % unicode_string

    # Explode
    root_logger.info(unicode_string)

if __name__ == "__main__":
    logging_test()

This explodes with UnicodeDecodeError on the logging.info() call.

At a lower level, Python's logging package is using the codecs package to open the log file, passing in the "UTF-8" argument as the encoding. That's all well and good, but it's trying to write byte strings to the file instead of unicode objects, which explodes. Essentially, Python is doing this:

file_handler.write(unicode_string.encode("UTF-8"))

When it should be doing this:

file_handler.write(unicode_string)

Is this a bug in Python, or am I taking crazy pills? FWIW, this is a stock Python 2.6 installation.


Solution

  • Check that you have the latest Python 2.6 - some Unicode bugs were found and fixed since 2.6 came out. For example, on my Ubuntu Jaunty system, I ran your script copied and pasted, removing only the '/home/ted/' prefix from the log file name. Result (copied and pasted from a terminal window):

    vinay@eta-jaunty:~/projects/scratch$ python --version
    Python 2.6.2
    vinay@eta-jaunty:~/projects/scratch$ python utest.py 
    printed unicode object: ô
    vinay@eta-jaunty:~/projects/scratch$ cat logfile.txt 
    ô
    vinay@eta-jaunty:~/projects/scratch$ 
    

    On a Windows box:

    C:\temp>python --version
    Python 2.6.2
    
    C:\temp>python utest.py
    printed unicode object: ô
    

    And the contents of the file:

    alt text

    This might also explain why Lennart Regebro couldn't reproduce it either.