WSGI内容编码

0 投票
2 回答
4729 浏览
提问于 2025-04-16 02:32

如果我运行下面这个Python 3.1的程序,在浏览器里看到的却是�,而不是正确的字符。这个文件本身是用UTF-8编码的,而且响应中也发送了相同的编码。

from wsgiref.simple_server import make_server

page = "<html><body>äöü€ßÄÖÜ</body></html>"

def application(environ, start_response):
    start_response("200 Ok", [("Content-Type", "text/html; charset=UTF-8")])
    return page

httpd = make_server('', 8000, application)
print("Serving on port 8000...")
httpd.serve_forever()

响应中“UTF-8”设置得很正确:

HTTP/1.0 200 Ok
Date: Mon, 09 Aug 2010 16:35:02 GMT
Server: WSGIServer/0.1 Python/3.1.1+
Content-Type: text/html; charset=UTF-8

这里到底出了什么问题呢?

2 个回答

0

这些字符不是 UTF-8 编码的,而是 latin-1 编码的。如果你把这些字符直接放到你的 Python 源代码里(其实不应该这样做),你需要在文件的顶部声明一下编码方式,添加以下这一行:

#-*- coding: latin-1 -*-

然后以 latin-1 的方式来处理:

start_response("200 Ok", [("Content-Type", "text/html; charset=latin-1")])

假设你是想用 UTF-8 来处理所有内容,你需要查一下这些字符的编码点。然后你可以这样做:

page = u"\x--\x--...\x--"

并将其作为 Unicode 来使用。

注意,你可以通过改变浏览器的编码来验证这一点;如果你手动把编码改成 latin-1,这些字符就能正常显示了。

8

在Python 3上,WSGI还没有正式推出。Web-SIG小组还没有就如何处理字符串(字节/Unicode)在Python 3.x中达成一致。

wsgiref基本上是一个自动转换工具,把Python 2的代码转成Python 3的代码;但它仍然存在一些问题,尤其是关于WSGI在3.x中到底意味着什么。所以,不要把它当作Python 3下WSGI应用的参考。

在3.2版本发布周期中,情况依然如此,真让人感到尴尬和沮丧。

return page

虽然WSGI在3.x中的情况仍然不明朗,但大多数人都同意,WSGI应用的响应内容应该主要是字节,而不是Unicode,因为HTTP是基于字节的协议。至于Unicode字符串是否会被接受,以及如果接受的话会用什么编码转换,仍然有待观察,所以最好避免这个问题,直接返回字节:

return [page.encode('utf-8')]

[]是必须的,因为WSGI应用应该返回一个可迭代的对象,每次输出和刷新一个项目。如果你单独传递一个字符串,它会被当作可迭代对象处理,一次返回一个字符,这样会严重影响性能。)

撰写回答