使用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字符时崩溃.我真的不关心打印,只关心它正在做的其他事情.
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())