Python 在Jinja2模板中使用utf-8字符

Python 在Jinja2模板中使用utf-8字符,python,python-2.7,utf-8,character-encoding,jinja2,Python,Python 2.7,Utf 8,Character Encoding,Jinja2,我试图在使用Jinja2呈现模板时使用utf-8字符。以下是我的模板的外观: <!DOCTYPE HTML> <html manifest="" lang="en-US"> <head> <meta charset="UTF-8"> <title>{{title}}</title> ... 现在的问题是,myvar是从消息队列读取的消息,可能包含那些特殊的utf8字符(例如“Séptimo Cine”) 渲

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

<!DOCTYPE HTML>
<html manifest="" lang="en-US">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
...
现在的问题是,myvar是从消息队列读取的消息,可能包含那些特殊的utf8字符(例如“Séptimo Cine”)

渲染的模板类似于:

...
    <title>S\u00e9ptimo Cine</title>
...
。。。
S\u00e9ptimo电影
...
我希望它是:

...
    <title>Séptimo Cine</title>
...
。。。
塞普蒂莫电影
...
我做了好几次测试,但都没能成功

  • 我尝试在不使用.encode(“utf8”)的情况下设置title变量,但它引发了一个异常(ValueError:应为bytes对象,而不是unicode对象),因此我猜测初始消息是unicode

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

  • 我还确保我的模板是一个UTF-8文件,但这并没有什么区别


有什么想法吗?

尝试将“渲染”命令更改为此

template.render(index_variables).encode( "utf-8" )
Jinja2的文档说“这将以unicode字符串的形式返回呈现的模板。”

希望这有帮助

TL;博士:

  • template.render()
  • 在将呈现的unicode结果写入文件之前,将其编码为bytestring
这让我困惑了一阵子。因为你知道

index_file.write(
    template.render(index_variables)
)
在一条语句中,这基本上只是Python关注的一行,因此您得到的回溯是误导性的:我在重新创建测试用例时得到的异常不是发生在
template.render(index\u variables)
中,而是发生在
index\u file.write()
中。所以像这样把代码分解

output = template.render(index_variables)
index_file.write(output)
是诊断UnicodeEncodeError发生的确切位置的第一步

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

index_file.write(output.encode('utf-8'))
第二个错误是将一个由testring编码的
utf-8
传递到
template.render()
-。因此,假设您的
myvar
包含UTF-8,您需要首先将其解码为unicode:

index_variables['title'] = myvar.decode('utf-8')
所以,总而言之,这对我来说很有用:

# -*- 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'))

如果因为混合了多种语言(如我的例子)而没有任何效果,只需将“utf-8”替换为“utf-16”

此处的所有编码选项:


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

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

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

Python中的字符串是二进制字符串。要使用unicode,请使用:astring.decode('urf-8')。或者使用:从未来的导入unicode_Literal我确实尝试在呈现模板后添加编码(“utf-8”),但这还不够。只有在写入文件时,才需要将其编码回
utf-8
。这个答案当然有帮助。谢谢你详细的回答并指出我的错误。它现在可以工作了:)非常感谢。你为我节省了很多时间。在我的情况下,我正在打印到标准输出,我的错误是:
文件。。。print template.render(context=getContent(..)UnicodeEncodeError:“latin-1”编解码器无法对1064-1088位置的字符进行编码:序号不在范围内(256)
在尝试解决“getContent”调用中的问题30分钟后,我找到了您的答案,这突出表明问题在于打印!不要这样做。请不要传播这个。由于某种原因,
sys
模块上的此设置不可用;这是一个全局设置,任何依赖于隐式编码或解码的代码都会引发非ASCII文本异常,并因此而中断。这包括第三方库中的代码。我非常了解这篇文章,强烈反对。你有没有看到我的答案也贴在那里?这仍然是一个货物崇拜,每当一个UnicodeEncoding例外事件抬头时就会出现。这不是解决办法。
#!/usr/bin/env python
# -*- coding: utf-8 -*-

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