将一个遗留Django项目(基于Django 1.1)本地化为日语之后,当语言环境是日语时,一些日志(并非所有日志)都输出这样的内容:
Traceback (most recent call last):
File "/home/deploy/.pythonbrew/pythons/Python-2.7/lib/python2.7/logging/__init__.py", line 838, in emit
msg = self.format(record)
File "/home/deploy/.pythonbrew/pythons/Python-2.7/lib/python2.7/logging/__init__.py", line 715, in format
return fmt.format(record)
File "/home/deploy/.pythonbrew/pythons/Python-2.7/lib/python2.7/logging/__init__.py", line 467, in format
s = self._fmt % record.__dict__
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128)
造成这种情况的原因是什么?是否有简单的方法可以避免这种情况?如果没有,我怎么能更密切地调查这个问题,因为我甚至不知道哪些行调用失败的日志?提前谢谢。
答案 0 :(得分:3)
找出字符串的方法是编辑日志记录模块,为您提供有关错误的一些信息。您不必保留编辑内容,只需修改它们足以找出导致问题的原因。
例如,在“/home/deploy/.pythonbrew/pythons/Python-2.7/lib/python2.7/logging/__init__.py”中,第467行是这一行:
s = self._fmt % record.__dict__
将其更改为:
try:
s = self._fmt % record.__dict__
except UnicodeError:
import pdb
pdb.set_trace()
然后当UnicodeDecodeError发生时,您将被放入调试器中。您可以检查格式字符串和记录以确定问题所在。
这可能是劳动密集型的,所以另一种选择是:
try:
s = self._fmt % record.__dict__
except UnicodeError:
s = "*** Couldn't log properly: %r against %r" % (self._fmt, record.__dict__)
这样,日志将包含一行指示失败的数据,并且每个失败的日志行都会有一行。如果您随后检查日志文件,则可能会发现许多问题行。
不要忘记保留logging / __ init__.py文件的原始版本,以便在完成调试后可以恢复它。
这个问题的难点在于,可能会有许多违规行,在您的代码中散布,除非您拥有100%的代码覆盖率且可以保证,否则您无法使用这样的特殊技术捕获所有这些行。在测试过程中击中了所有这些。
有关Python中Unicode的基本问题的更多信息,请参阅Pragmatic Unicode, or, How Do I Stop The Pain?。
答案 1 :(得分:0)
为了避免这种异常,我在每个.py:
的顶部写下这一行# This Python file uses the following encoding: utf-8
来自PEP:
- 醇>
没有解释器行,使用纯文本:
# This Python file uses the following encoding: utf-8 import os, sys ...