将 Python 3 中的 UTF-8 字符打印到 Web

Printing UTF-8 characters in Python 3 to the web

我正在尝试将 Python 3 中的 Unicode 字符打印到网络上。在 Python 我可以 运行:

print("Content-Type: text/html; charset=utf-8\n")
print("\u00EA")

当从命令行 运行 时,它正确地吐出:

Content-type: text/html; charset=utf-8

ê

但是当运行从网络作为Apache下的CGI脚本时,它会抛出一个错误:

UnicodeEncodeError: 'ascii' codec can't encode character '\xea' in position 0: ordinal not in range(128)

关于如何让 Python 3 将 UTF-8 打印到网络上的任何建议?谢谢!

编辑:locale 在我的帐户和 www-data(Apache 的帐户)中的输出是:

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=

您必须将数据显式编码为 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)

感谢这里用户的反馈,我得以拼凑出一个解决方案:

  1. Content-Type 行必须包含 charset=utf-8
  2. Apache 的配置文件必须包含 SetEnv LANG en_US.UTF-8.

一个很棒的调试工具是打印 sys.stdout.encoding 的值,它应该 return "UTF-8",而不是 "ANSI_X3.4-1968".