【问题标题】:Python cgi encoding / special charactersPython cgi编码/特殊字符
【发布时间】:2012-12-09 20:20:20
【问题描述】:

从本地控制台运行时会打印“Test: £17”,但从 Web 浏览器运行时只会打印“Test:”。通过浏览器加载时如何纠正问题?谢谢!

#!/usr/bin/python3.2
print ("Content-Type: text/html")
print ("")

y = "£17"
print ("Test:", y)

【问题讨论】:

  • print(y) 只做什么?
  • 你需要使用HTML转义-尝试打印£17
  • @JonClements:这是可选的,真正的问题是 Python print() 自动编码到终端,但是对于 CGI,使用了错误的编码。

标签: python python-3.x encoding cgi


【解决方案1】:

当打印到控制台时,Python 会将 unicode 值编码为字节。

发送到浏览器时显式编码,直接写入sys.stdout

#!/usr/bin/python3.2
import sys
out = sys.stdout
out.write(b"Content-Type: text/html; charset=utf8\r\n")
out.write(b"\r\n")

y = "£17"
out.write("Test: {0}\r\n".format(y).encode(encoding='utf8'))

请注意,HTTP 标头应该使用 \r\n(回车,换行)组合,真的。我还添加了用于Content-Type 标头的编码,以便浏览器知道如何再次对其进行解码。

对于 HTML,您确实希望使用 character entity references 而不是 Unicode 代码点:

y = "£17"
out.write("Test: {0}\r\n".format(y).encode(encoding='utf8'))

此时您也可以只使用 ASCII 作为编码。

如果你真的、真的、真的想使用print(),那么用正确的编码重新打开stdout

utf8stdout = open(1, 'w', encoding='utf-8', closefd=False) # fd 1 is stdout

print("Content-Type: text/html; charset=utf8", end='\r\n', file=utf8stdout)
print("", end='\r\n', file=utf8stdout)

y = "£17"
print("Test:", y, end='\r\n', file=utf8stdout)

您可以使用functools.partial() 稍微简化一下:

from functools import partial
utf8print = partial(print, end='\r\n', file=utf8stdout)

然后使用utf8print() 而不使用额外的关键字:

utf8print("Content-Type: text/html; charset=utf8")
utf8print("")
# etc.

另请参阅Python Unicode HOWTO,了解有关 Python 如何设置输出编码的详细信息,以及有关打印和编码的 this question here on Stack Overflow

【讨论】:

  • 非常感谢!最后一个选项适用于测试用例和我正在做的事情。我想使用第一个建议,但它似乎没有正常工作 =/ 这是一个巨大的帮助,我也学到了很多,并且会影响我做几件事的方式。再次感谢。
  • 这种方法似乎有最大输出,我现在正在排除故障。如果我使用 utf8print 过多,我会收到服务器错误。
  • @stackity:我怀疑任何事情都会被淘汰;你更有可能犯了一个不同的错误。 :-)
  • 我回来删除评论(希望没有人回复),你是对的,与本地主机相比,我的共享主机限制了我可以创建的线程数量。我的诊断不正确。再次感谢!
猜你喜欢
  • 2016-10-19
  • 2013-06-07
  • 1970-01-01
  • 1970-01-01
  • 2014-09-17
  • 1970-01-01
  • 1970-01-01
  • 2018-05-28
相关资源
最近更新 更多