将Python 3中的UTF-8字符打印到网络上

问题描述

我正在尝试将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=

解决方法

由于这里用户的反馈,我得以找到一个解决方案:

  1. Content-Type行中必须包含charset=utf-8
  2. 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)