Подтвердить что ты не робот

Использование символов utf-8 в шаблоне Jinja2

Я пытаюсь использовать символы utf-8 при рендеринге шаблона с помощью Jinja2. Вот как выглядит мой шаблон:

<!DOCTYPE HTML>
<html manifest="" lang="en-US">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
...

Переменная title задана примерно так:

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).

Представленный шаблон выглядит примерно так:

...
    <title>S\u00e9ptimo Cine</title>
...

и я хочу, чтобы это было:

...
    <title>Séptimo Cine</title>
...

Я сделал несколько тестов, но я не могу заставить это работать.

  • Я попытался установить переменную title без .encode( "utf8" ), но она выдает исключение (ValueError: ожидается объект байтов, а не объект unicode), поэтому я предполагаю, что начальное сообщение является unicode

  • Я использовал chardet.detect, чтобы получить кодировку сообщения (это "ascii" ), а затем выполнил следующее: myvar.decode( "ascii" ). encode ( "cp852" ), но заголовок все еще не отображается правильно.

  • Я также убедился, что мой шаблон является файлом UTF-8, но это не повлияло.

Любые идеи о том, как это сделать?

4b9b3361

Ответ 1

TL; ДР:

  • Пропустить Unicode до template.render()
  • Кодировать результат рендеринга unicode к байтовой строке перед записью в файл

Это немного озадачило меня. Потому что вы делаете

index_file.write(
    template.render(index_variables)
)

в одном утверждении, что в основном только одна строка, в которой находится Python, так что трассировка, которую вы получаете, вводит в заблуждение: исключение, которое я получил, когда воссоздание тестового примера не произошло в template.render(index_variables), а в index_file.write(). Итак, разделив код таким образом

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

был первым шагом для диагностики того, где именно происходит UnicodeEncodeError.

Jinja возвращает unicode, чтобы вы могли визуализировать шаблон. Поэтому вам нужно закодировать результат до байта, прежде чем вы сможете записать его в файл:

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

Вторая ошибка заключается в том, что вы передаете utf-8 закодированную bytestring на template.render() - Jinja хочет unicode. Итак, если ваш myvar содержит UTF-8, вам нужно сначала его декодировать в Юникод:

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

Ответ 2

Попробуйте изменить команду визуализации на это...

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

Документация Jinja2 говорит: "Это вернет обработанный шаблон в виде строки в Юникоде".

http://jinja.pocoo.org/docs/api/?highlight=render#jinja2.Template.render

Надеюсь, это поможет!

Ответ 3

И если ничего не работает, потому что у вас есть сочетание языков, как в моем случае, просто замените "utf-8" на "utf-16"

Все параметры кодировки здесь:

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

Ответ 4

Добавьте следующие строки в начало вашего script, и он будет работать нормально без каких-либо дальнейших изменений:

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

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