使用python解释器
>>> print u'\xe9'
é
但如果我在Django视图中放入相同的行,我会得到
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 0:
ordinal not in range(128)
为什么?
我使用的是Django 1.5.1和python 2.6.6。
一些背景......我有一个Django项目,它使用第三方模块处理一些字符串,并打印它们。当在Django之外使用模块时,它工作正常,但是当它作为Django项目的一部分使用时,它在尝试打印非ascii字符时崩溃。我并不十分关心印刷,只关心它正在做的其他事情。
答案 0 :(得分:5)
Python print
语句将自动将Unicode值编码为用于sys.stdout
的编解码器。
在您的控制台或终端中,输出编解码器会自动从系统中获取。但是,如果您的输出重定向到文件,则使用默认编解码器ASCII
。
在服务器上运行的Django应用程序不能依赖输出编解码器设置为可以处理所有unicode代码点的东西。不要使用print
,而是使用日志记录,并明确编码。
如果第三方库正在执行此操作,您需要联系维护人员并要求他们停止这样做。您可以使用上下文管理器将每个调用包装到该库中,该上下文管理器使用虚拟对象(具有合适的sys.stdout
属性的对象)交换.encoding
,但这实际上只是一个间隙测量:
from contextlib import contextmanager
from io import BytesIO
import sys
@contextmanager
def capture_stdout_unicode(codec='UTF-8'):
output = BytesIO()
output.encoding = codec
orig, sys.stdout = sys.stdout, output
try:
yield output
finally:
sys.stdout = orig
然后使用它:
with capture_stdout_unicode() as out:
api_call_that_prints()
logger.info(out.getvalue())