Страницы

Поиск по вопросам

воскресенье, 15 декабря 2019 г.

Проблемы с кодировкой при отправке html-шаблона с русским текстом: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe0

#python #python_3x #utf_8 #windows_10 #flask


Дано: Windows 10, Python 3.4, PyScripter, Flask
Есть файл (допустим main.py) в котором вызывается шаблон

def index():
    return render_template('index.html')


в index.html поле для ввода

Если так запустить localhost:5000 то все ок, но если изменить на русский язык
то выдает ошибку builtins.UnicodeDecodeError UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe0 in position 437: >invalid continuation byte Python3 по умолчанию использует кодировку utf-8, в файле html также meta charset="utf-8" прописано. Traceback начинает ругаться на строчку return render_template('index.html') в main.py.


Ответы

Ответ 1



Недостаточно прописать , нужно ещё сам файл сохранить именно в кодировке utf-8. Зачем? Прописанная мета никак не влияет на содержимое файла. Она лишь даёт подсказку браузеру, какую кодировку использовать для декодирования файла. Можно написать мету cp1251, а сохранить всё равно в utf-8 — это будет работать, только в браузере будут кракозябры, потому что он послушается подсказку и попытается раскодировать utf-8 байты как cp1251 символы. Flask не использует мету. Он (точнее, Jinja2) тупо читает текстовый файл и интерпретирует его как шаблон Jinja2. А HTML ли там, или CSS, или JS, или JSON — фласку пофиг. Шаблонизатор Jinja2 по умолчанию пытается прочитать файлы как utf-8, и ему плевать на ваши меты. Но это ещё не всё: вся обработка шаблона завязана на юникодных строках (у которых для простоты можно считать, что они не имеют конкретной кодировки, так как это деталь реализации питона, для нас не важная), и render_template возвращает юникодную (не байтовую!) строку независимо от того, в какой кодировке был сохранён файл и что там понаписано в метах. Перед отправкой ответа браузера Flask должен обратно закодировать юникодную строку в какие-то байты, и по умолчанию для этого используется кодировка utf-8. Таким образом неважно, в какой кодировке сохранён файл и что написано в мете — браузеру будут отправлены всегда utf-8 байты! Браузер будет пытаться раскодировать эти байты согласно подсказке, прописанной в мете. То есть если вы замените кодировку по умолчанию в Jinja2 (и при этом не замените в Flask Response), то кодировка исходного файла-шаблона и кодировка, прописанная в мете, вообще не обязаны совпадать :) Кодировки Python-файлов и кодировки по умолчанию в самом Python в данном конкретном случае не играют никакой роли.

Комментариев нет:

Отправить комментарий