在 traceback.print_exc() 中使用 sys.stdout 时出现 UnicodeDecodeError
我在使用 traceback.print_exc(file=sys.stdout)
的时候遇到了 UnicodeDecodeError
错误。我现在用的是 Python3.4,而在 Python2.7 中没有这个问题。
我是不是漏掉了什么?我该怎么确保 sys.stdout
能正确地传递编码和解码给 traceback.print_exc()
呢?
我的代码大概是这样的:
try:
# do something which might throw an exception
except Exception as e:
# do something
traceback.print_exc(file=sys.stdout) # Here I am getting the error
错误日志:
traceback.print_exc(file=sys.stdout)
File "C:\Python34\lib\traceback.py", line 252, in print_exc
print_exception(*sys.exc_info(), limit=limit, file=file, chain=chain)
File "C:\Python34\lib\traceback.py", line 169, in print_exception
for line in _format_exception_iter(etype, value, tb, limit, chain):
File "C:\Python34\lib\traceback.py", line 153, in _format_exception_iter
yield from _format_list_iter(_extract_tb_iter(tb, limit=limit))
File "C:\Python34\lib\traceback.py", line 18, in _format_list_iter
for filename, lineno, name, line in extracted_list:
File "C:\Python34\lib\traceback.py", line 65, in _extract_tb_or_stack_iter
line = linecache.getline(filename, lineno, f.f_globals)
File "C:\Python34\lib\linecache.py", line 15, in getline
lines = getlines(filename, module_globals)
File "C:\Python34\lib\linecache.py", line 41, in getlines
return updatecache(filename, module_globals)
File "C:\Python34\lib\linecache.py", line 127, in updatecache
lines = fp.readlines()
File "C:\Python34\lib\codecs.py", line 313, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe7 in position 5213: invalid continuation byte
1 个回答
追踪模块想要在错误追踪信息中包含源代码的行。通常,错误追踪信息只包含指向源代码的指针,而不是源代码本身,因为Python执行的是编译后的字节码。在字节码中,有一些提示可以告诉我们这个字节码来自哪个源代码行。
为了显示源代码,实际的源文件会从磁盘中读取,这个过程是通过 linecache
模块来完成的。这也意味着Python需要确定这些文件的编码方式。Python 3 源文件的默认编码是UTF-8,但你可以设置一个 PEP 263 注释 来告诉Python如果你使用了其他编码。
因为源代码是在代码已经加载并发生错误追踪后才被读取的,所以有可能你在启动脚本后 修改 了源代码,或者 存在一个字节缓存文件(在 __pycache__
子目录中),这个文件看起来是新的,但实际上与你的源文件不再匹配。
无论如何,当你启动脚本时,Python能够重新使用一个字节缓存文件或正常读取源代码并运行你的代码。但是当打印错误追踪信息时,至少有 一个 源代码文件无法被解码为UTF-8。
如果你能可靠地重现这个错误追踪(也就是说,重新启动Python脚本时没有编码问题,但打印错误追踪失败),那么很可能是某个地方有一个过时的字节码文件,甚至可能指向一个现在只包含二进制数据而不是普通源代码的文件名。
如果你知道如何使用 pdb
模块,可以在 traceback.print_exc()
调用之前添加一个 pdb.set_trace()
调用,跟踪 linecache
模块正在加载哪些文件名。
否则,你可以 编辑 你的 C:\Python34\lib\traceback.py
文件,在 linecache.checkcache(filename)
行之前插入 print('Loading {} from the linecache'.format(filename))
语句。