CherryPy在Jinja2模板中无法正确处理非ASCII字符

2 投票
2 回答
4615 浏览
提问于 2025-04-16 11:21

我正在尝试用 Python 2.7.1、Jinja 2.5.2 和 CherryPy 3.1.2 来搭建一个网站。我使用的 Jinja 模板是 UTF-8 编码的。不过,我发现这些模板中的某些字符变成了问号和其他奇怪的符号。如果我直接渲染这些模板,不用 Jinja,就没有这个问题。我发现可以通过在所有处理程序的输出上调用 .encode("utf-8") 来解决这个问题,但这样做会让我的代码看起来很乱,感觉很烦人。有没有人知道为什么会出现这个问题,或者该怎么解决?我还写了一个小脚本来演示这个问题。文件 "char.txt" 是一个只有 2 字节的文件,里面只包含一个 UTF-8 编码的 "»" 字符。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os, jinja2, cherrypy
jinja2env = jinja2.Environment(loader=jinja2.FileSystemLoader("."))

class Test(object):
    def test1(self):
        #doesn't work
        #curl "http://example.com/test1"
        #?
        return jinja2env.get_template("char.txt").render()
    test1.exposed = True

    def test2(self):
        #works
        #curl "http://example.com/test2"
        #»
        return open("char.txt").read()
    test2.exposed = True

    def test3(self):
        #works, but it is annoying to have to call this extra function all the time
        #curl "http://example.com/test3"
        #»
        return jinja2env.get_template("char.txt").render().encode("utf-8")
    test3.exposed = True

cherrypy.config["server.socket_port"] = 8500
cherrypy.quickstart(Test())

2 个回答

6

jinja2 只支持 Unicode。看起来,当客户端没有发送 Accept-Header 时,cherrypy 通常会使用 utf-8 作为输出编码,但如果这个头部是空的,它就会退回到 iso-8859-1。

tools.encode.encoding:如果指定了这个选项,工具会在响应无法用它编码时报错。否则,工具会使用 'Accept-Charset' 请求头来尝试提供合适的编码,通常情况下,如果客户端没有指定字符集,它会尝试 utf-8,但如果客户端发送了一个空的 'Accept-Charset' 头部,它会遵循 RFC 2616 的规定,尝试使用 ISO-8859-1。

http://www.cherrypy.org/wiki/BuiltinTools#tools.encode

我可以通过像这样使用 encode 工具来解决这个问题:

cherrypy.config["tools.encode.on"] = True
cherrypy.config["tools.encode.encoding"] = "utf-8"

示例

$ curl "http://127.0.0.1:8500/test1"
»
$ curl "http://127.0.0.1:8500/test2"
»
$ curl "http://127.0.0.1:8500/test3"
»
2

来自CherryPy教程

tools.encode:这个工具会自动把Python中的Unicode字符串格式的响应转换成合适的编码格式,比如Latin-1或UTF-8。

这听起来就是你要找的答案。

撰写回答