我有一个小型记录器函数,可以返回两个处理程序,以便同时记录到RotatingFileHandler和sys.stdout。
解决方法是在调用日志记录函数的代码中对每一个获取的消息都进行UTF8编码,例如这样:
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
一般情况下这个程序可以正常运行,但是记录日志时遇到某些字符串编码为cp1252,在使用日志函数将它们打印到标准输出(stdout)时会产生(非致命性)错误。需要指出的是,这些字符在错误信息中打印没有任何问题。将它们记录到文件中也不会出现问题。只有控制台 - 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,但没有明显的效果。
更新: 事实证明我很蠢。仅因为控制台打印出错误消息并不意味着控制台打印是错误的根本原因。我正在研究其他问题的答案,这些问题已经被推荐给我,过了一会儿我意识到我对函数的“if echo”部分所做的任何更改都没有影响结果。最后一次检查是注释掉整个块,我仍然得到错误。那时,我意识到问题实际上是由于在写入文件时未强制执行UTF8而引起的。按照@michael-ruth建议的方法将简单的kwarg encoding ='utf-8'添加到RotatingFileHandler中解决了我的问题。 PS 我不确定如何处理这种情况,因为虽然那个答案解决了我的问题,但它并不是我最初询问或该问题所建议的内容,因为我最初误解了根本原因。我仍将其视为解决方案,并赞同两个答案。我还将编辑问题,以免误导将来的读者认为它将回答该问题,而实际上并非如此。