Python中如何将所有日志消息编码为UTF-8格式
日志函数Unicode编码报错问题排查与解决
原始日志实现
我编写了一个简易日志函数,最多可返回两个处理器,同时将日志输出到RotatingFileHandler和sys.stdout。
import os, logging, sys from logging.handlers import RotatingFileHandler from config import * def get_logger(filename, log_level_stdout=logging.WARNING, log_level_file=logging.INFO, echo=True): logger = logging.getLogger(__name__) if not os.path.exists(PATH + '/Logs'): os.mkdir(PATH + '/Logs') logger.setLevel(logging.DEBUG) if echo: prn_handler = logging.StreamHandler(sys.stdout) prn_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s')) prn_handler.setLevel(log_level_stdout) logger.addHandler(prn_handler) file_handler = RotatingFileHandler(PATH + '/Logs/' + filename, maxBytes=1048576, backupCount=3) file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s')) file_handler.setLevel(log_level_file) logger.addHandler(file_handler) return logger
问题现象
该函数整体运行正常,但部分包含特殊字符的字符串输出时会触发编码错误,最初误判为sys.stdout输出导致的问题,报错栈信息如下:
--- Logging error --- Traceback (most recent call last): File "C:\Program Files\Python38\lib\logging\__init__.py", line 1084, in emit stream.write(msg + self.terminator) File "C:\Program Files\Python38\lib\encodings\cp1252.py", line 19, in encode return codecs.charmap_encode(input,self.errors,encoding_table)[0] UnicodeEncodeError: 'charmap' codec can't encode character '\u1ecd' in position 65: character maps to <undefined> Call stack: File "script.py", line 147, in <module> logger.info(f"F-String with a name in it: '{name}'.") Message: "F-String with a name in it: 'Heimstọð'." Arguments: ()
临时解决方案
最初的临时处理方案是调用日志方法时手动将字符串编码为utf8:
logger.info((f"F-String with a name in it: '{name}'.").encode('utf8'))
该方案既不优雅也不高效,同时尝试在Windows系统变量中设置PYTHONIOENCODING为utf-8,也没有解决问题。
根因排查与最终修复
后续进一步排查发现,即使注释掉控制台输出的相关代码,错误仍然会抛出,最终确认问题根源是RotatingFileHandler初始化时未强制指定UTF-8编码,默认使用了系统的cp1252编码,遇到特殊字符就会触发编码错误。
修复方案仅需在初始化RotatingFileHandler时添加encoding='utf-8'参数即可,修正后的对应代码行如下:
file_handler = RotatingFileHandler(PATH + '/Logs/' + filename, maxBytes=1048576, backupCount=3, encoding='utf-8')
说明
最初误判为控制台输出导致问题,实际根因为文件处理器未指定编码,修改问题描述避免误导后续读者。
内容的提问来源于stack exchange,提问作者Midnight
相关产品推荐
相关产品推荐

