【问题标题】:WSGI content encodingWSGI 内容编码
【发布时间】:2011-03-27 09:56:16
【问题描述】:

如果我执行以下 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

这里有什么问题?

【问题讨论】:

    标签: python http utf-8 character-encoding content-type


    【解决方案1】:

    那些字符不是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,则字符将正常显示。

    【讨论】:

    • 我认为 Python >= 3 不需要 #-*- coding: ...。显示的字符原则上可以直接用 UTF-8 编写。
    【解决方案2】:

    Python 3 上的 WSGI 还不存在。 Web-SIG 尚未就 Python 3.x 中如何处理字符串(字节/unicode)得出任何结论。

    wsgiref 很大程度上是一种自动的 2to3 转换;除了 3.x 上的 WSGI 的实际含义之外,它仍然存在问题。不要依赖它作为 WSGI 应用程序在 Python 3 下如何工作的参考。

    这种情况仍然进入 3.2 发布周期真是令人尴尬和沮丧。

    return page
    

    好吧,虽然 3.x 的 WSGI 仍然是一个未知因素,但最一致的一点是 WSGI 应用程序的响应主体通常应该是字节而不是 unicode,因为 HTTP 是基于字节的协议。 Unicode 字符串是否会被接受——如果接受,它们将使用什么编码进行转换——还有待观察,因此请避免该问题并返回字节:

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

    ([] 是必需的,因为 WSGI 应用程序应该返回一个输出并一次刷新一个项目的迭代。如果你自己传递一个字符串,它被用作一个迭代并一次返回一个字符,这性能太差了。)

    【讨论】:

    • 感谢赐教。但是return page.encode('utf-8') 不起作用。我从 WSGI 运行时收到以下错误:AssertionError: write() argument must be a string or bytes.
    • 是的,对不起,我后来编辑了关于[] 的内容! [] 丢失的情况对于字节字符串来说比对于 unicode 更失败,因为在 Python 3 中,b'A'[0] 是整数 65,而不是 b'A'。 IMO,这几乎是 Python 3 犯的最严重的错误。
    • 我不会说这是个谜。 b“A”代表一个字节而不是一个字符是有道理的。这样就几乎不可能像以前那样混淆 str 和 unicode。
    • 我对 Python 3.5 也有同样的看法。我不知道是否有任何改变,但直到我在 return 中执行 page.encode,它才起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-27
    • 2023-03-09
    • 2018-02-27
    • 2011-08-12
    • 1970-01-01
    • 2014-02-22
    相关资源
    最近更新 更多