将Python 3中的UTF-8字符打印到web
我正在尝试将一个Unicode字符从Python3打印到web上。在Python中,我可以运行:将Python 3中的UTF-8字符打印到web,python,utf-8,python-unicode,Python,Utf 8,Python Unicode,我正在尝试将一个Unicode字符从Python3打印到web上。在Python中,我可以运行: print("Content-Type: text/html; charset=utf-8\n") print("\u00EA") 从命令行运行时,它会正确地输出: 内容类型:text/html;字符集=utf-8 ê 但当在Apache下以CGI脚本的形式从web运行时,会抛出一个错误: UnicodeEncodeError:“ascii”编解码器无法在中
print("Content-Type: text/html; charset=utf-8\n")
print("\u00EA")
从命令行运行时,它会正确地输出:
内容类型:text/html;字符集=utf-8
ê
但当在Apache下以CGI脚本的形式从web运行时,会抛出一个错误:
UnicodeEncodeError:“ascii”编解码器无法在中编码字符“\xea”
位置0:序号不在范围内(128)
关于如何让Python3将UTF-8打印到web上有什么建议吗?谢谢
编辑:我的帐户和www-data(Apache的帐户)中的locale
的输出为:
您必须显式地将数据编码为utf-8(否则Python会尝试猜测,而在您的例子中,它猜测的是ASCII,结果不太好)。因此,请这样做:
sys.stdout.buffer.write(text.encode('utf-8'))
这将修复您的错误。
请注意,我使用的是sys.stdout.buffer.write
而不是print
,因为buffer.write
可以处理原始字节(UTF-8是原始字节数组,而不是字符串)
除此之外,您应该告诉客户机(浏览器)数据是以utf-8的形式提供的(否则浏览器也必须猜测,这可能会成功,但最好是明确的),例如
读取文件时,请使用上下文管理器 幕后打开和关闭文件是为您完成的,所以您不必记住它 打开(文件名,编码为utf-8')为f的
:
text=f.read()
打印(文本)
多亏了这里用户的反馈,我才能够拼凑出一个解决方案:
内容类型
行必须包括charset=utf-8
SetEnv LANG en_US.UTF-8
一个很好的调试工具是打印sys.stdout.encoding的值,它应该返回“UTF-8”,而不是“ANSI_X3.4-1968”。这是我尝试过的事情之一,但在命令行和web浏览器上都会产生这样的结果:b'L\xc3\xaa Qu\xc3\xbd\xc4\x90\xc3\xb4n\n'Python 3字符串已经是Unicode了。这更多的是操作系统/控制台问题。也许操作系统的区域设置配置为使用ASCII?如果在Linux上,LC_是怎么设置的?@NeilFraser是的,我写代码太快了,没有检查。它不能与
打印
一起使用。我修正了答案,试试看。@PanagiotisKanavos Python 3字符串是unicode,不是UTF-8。它们需要转换为UTF-8字节数组print
将通过检查stdout
的编码来自动执行此操作,这对于仅打印到控制台是很好的。生成HTTP响应应该更明确地说明编码。只是不要使用printf
?将操作系统区域设置配置为使用UTF8?顺便说一句,此页面就像其他网页一样是UTF8。不需要特殊处理,这就是为什么您可以读取这些越南语字符而无需编码,或者联系SO的团队要求特殊处理。运行apache进程的用户的区域设置是什么?问题是printf和控制台。您正在写入控制台,而不是文件,这意味着Python必须使用控制台的编码。如果您的环境配置为使用拉丁文1或更差的US-ASCII,则文本将被破坏。在Linux上,这是由LC\u ALL
控制的。Windows本机是Unicode,但控制台GUI是特定于语言环境的,需要设置以显示UTF8。这不应该影响流程间的沟通,尽管这个答案看起来像你想要的。选择4(通过Apache的$LANG
看起来是最好的方法,摆弄sys。在其他答案中建议使用defaultencoding
,但在我看来,这是非常粗糙的。问题的代码已经使用了显式编码。这有什么区别?这是Python文件处理的一个很好的指针。与当前问题没有直接关系,但是很高兴知道。谢谢!
sys.stdout.buffer.write(text.encode('utf-8'))
print("Content-Type: text/html; charset=utf-8\n")