关于python:在jinja2模板中使用utf-8字符

Using utf-8 characters in a Jinja2 template

我尝试在使用jinja2呈现模板时使用utf-8字符。以下是我的模板的外观:

1
2
3
4
5
6
<!DOCTYPE HTML>
<html manifest="" lang="en-US">
<head>
    <meta charset="UTF-8">
    {{title}}
...

标题变量设置如下:

1
2
3
4
5
6
7
8
9
10
index_variables = {'title':''}
index_variables['title'] = myvar.encode("utf8")

template = env.get_template('index.html')
index_file = open(preview_root +"/" +"index.html","w")

index_file.write(
    template.render(index_variables)
)
index_file.close()

现在,问题在于myvar是从消息队列读取的消息,可以包含那些特殊的utf8字符(例如"s_ptimo cine")。

呈现的模板如下所示:

1
2
3
...
    S\u00e9ptimo Cine
...

我希望它是:

1
2
3
...
    Séptimo Cine
...

我做了几次测试,但都做不到。

  • 我试图在没有.encode("utf8")的情况下设置标题变量,但它引发了一个异常(valueerror:应为bytes对象,而不是unicode对象),所以我猜初始消息是unicode

  • 我使用chardet.detect获取消息的编码(它是"ascii"),然后执行以下操作:myvar.decode("ascii").encode("cp852"),但标题仍然没有正确呈现。

  • 我还确定了我的模板是一个UTF-8文件,但是没有什么区别。

有什么办法吗?


DR:

  • 将unicode传递到EDOCX1[0]
  • 在将呈现的unicode结果写入文件之前,将其编码为bytestring

这让我困惑了一段时间。因为你这样做

1
2
3
index_file.write(
    template.render(index_variables)
)

在一条语句中,这基本上只是一行关于python的内容,所以您得到的回溯是误导性的:我在重新创建测试用例时得到的异常并没有在template.render(index_variables)中发生,而是在index_file.write()中发生。所以像这样拆分代码

1
2
output = template.render(index_variables)
index_file.write(output)

这是诊断UnicodeEncodeError究竟发生在哪里的第一步。

Jinja返回unicode,让它呈现模板。因此,在将结果写入文件之前,需要将结果编码为字节串:

1
index_file.write(output.encode('utf-8'))

第二个错误是,您传入了由estring编码的utf-8template.render(),jinja需要unicode。所以假设您的myvar包含utf-8,您需要先将其解码为unicode:

1
index_variables['title'] = myvar.decode('utf-8')

所以,综合起来,这对我来说是可行的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# -*- coding: utf-8 -*-

from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('myproject', 'templates'))


# Make sure we start with an utf-8 encoded bytestring
myvar = 'Séptimo Cine'

index_variables = {'title':''}

# Decode the UTF-8 string to get unicode
index_variables['title'] = myvar.decode('utf-8')

template = env.get_template('index.html')

with open("index_file.html","w") as index_file:
    output = template.render(index_variables)

    # jinja returns unicode - so `output` needs to be encoded to a bytestring
    # before writing it to a file
    index_file.write(output.encode('utf-8'))


尝试将渲染命令更改为…

1
template.render(index_variables).encode("utf-8" )

Jinja2的文档说,"这将以unicode字符串的形式返回呈现的模板。"

http://jinja.pocoo.org/docs/api/?highlight=渲染jinja2.template.render

希望这有帮助!


如果因为你有多种语言的混合(就像我的例子一样),什么都不起作用,只需将"utf-8"替换为"utf-16"

这里的所有编码选项:

https://docs.python.org/2.4/lib/standard-encodings.html版本


将以下行添加到脚本的开头,它将正常工作,无需进一步更改:

1
2
3
4
5
6
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
reload(sys)
sys.setdefaultencoding("utf-8")