问题描述
我正在尝试将Unicode字符从Python 3打印到网络上。在Python中,我可以运行:
print("Content-Type: text/html; charset=utf-8\n")
print("\u00EA")
从命令行运行时,它会正确吐出:
内容类型:text / html; charset = utf-8
ê
但是当在Apache下作为CGI脚本从Web运行时,它会引发错误:
UnicodeEncodeError:'ascii'编解码器无法在其中编码字符'\ xea' 位置0:序数不在范围内(128)
关于如何获取Python 3将UTF-8打印到网络上的任何建议?谢谢!
编辑:我的帐户和locale
(Apache的帐户)中的www-data
的输出是:
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
解决方法
由于这里用户的反馈,我得以找到一个解决方案:
-
Content-Type
行中必须包含charset=utf-8
。 - Apache的配置文件必须包含
SetEnv LANG en_US.UTF-8
。
一个很棒的调试工具是打印sys.stdout.encoding
的值,它应该返回“ UTF-8”,而不是“ ANSI_X3.4-1968”。
您必须将数据显式编码为utf-8(否则Python会尝试猜测,并且在您的情况下,它会猜测ASCII,但效果不佳)。因此,请执行以下操作:
sys.stdout.buffer.write(text.encode('utf-8'))
这将纠正您的错误。
请注意,我使用的是sys.stdout.buffer.write
而不是print
,因为buffer.write
可以处理原始字节(而UTF-8是原始字节数组,而不是字符串)。
除此之外,您应该告诉客户端(浏览器)数据以utf-8格式提供(否则浏览器也必须猜测,可能会成功,但是最好是明确的),例如
print("Content-Type: text/html; charset=utf-8\n")
,
读取文件时,请使用上下文管理器。
幕后打开和关闭文件已为您完成,因此您不必记住它。
with open(filename,encoding='utf-8') as f:
text = f.read()
print(text)