Spec-Zone.ru › Werkzeug 0.16

Unicode

С ранних дней Python 2, юникод был частью всех стандартных сборок Python. Это позволяет разработчикам создавать приложения, работающие с не-ASCII символами простым способом. Но работа с юникодом требует базовых знаний об этой теме, особенно при работе с библиотеками, которые его не поддерживают.

Werkzeug использует юникод во всех местах, где предполагаются текстовые данные, даже если стандарт HTTP не поддерживает юникод. По существу, все входящие данные декодируются из указанного набора символов (по умолчанию utf-8), чтобы вы больше не работали с байтовыми строками. Выходящие данные в юникоде затем кодируются обратно в целевой набор символов.

Unicode в Python

В Python 2 существует два основных типа строк: str и unicode. str может содержать закодированные данные юникода, но они всегда представляются в виде байтов, в то время как тип unicode не содержит байтов, а символьные точки. Что это значит? Представьте себе немецкий диакритический знак ö. В ASCII вы не можете представить этот символ, но в наборах символов latin-1 и utf-8 вы можете представить его, но они выглядят по-разному при кодировании:

>>> u'ö'.encode('latin1')
'\xf6'
>>> u'ö'.encode('utf-8')
'\xc3\xb6'

Таким образом, ö может выглядеть совершенно по-разному в зависимости от кодировки, что затрудняет с ним работу. Решение заключается в использовании типа unicode (как мы сделали выше, обратите внимание на префикс u перед строкой). Тип unicode не хранит байты для ö, а информацию о том, что это LATIN SMALL LETTER O WITH DIAERESIS.

Выполнение len(u'ö') всегда даст нам ожидаемое «1», но len('ö') может дать разные результаты в зависимости от кодировки 'ö'.

Unicode в HTTP

Проблема с юникодом заключается в том, что HTTP не знает, что такое юникод. HTTP ограничен байтами, но это не большая проблема, поскольку Werkzeug автоматически декодирует и кодирует все входящие и исходящие данные. По существу, это означает, что данные, отправленные из браузера в веб-приложение, по умолчанию декодируются из байтовой строки utf-8 в строку типа unicode. Данные, отправленные приложением обратно в браузер, которые еще не являются байтовой строкой, затем кодируются обратно в utf-8.

Обычно это «просто работает», и нам не нужно об этом беспокоиться, но есть ситуации, когда такое поведение проблематично. Например, уровень ввода-вывода Python 2 не поддерживает юникод. Это означает, что всякий раз, когда вы работаете с данными из файловой системы, вам нужно правильно их декодировать. Правильный способ загрузки текстового файла из файловой системы выглядит так:

f = file('/path/to/the_file.txt', 'r')
try:
    text = f.decode('utf-8')    # assuming the file is utf-8 encoded
finally:
    f.close()

Также есть модуль codecs, который предоставляет функцию open, которая автоматически декодирует из указанной кодировки.

Обработка ошибок

Функции, выполняющие внутреннюю кодировку или декодирование, принимают ключевой аргумент errors, который передается в str.decode() и str.encode(). По умолчанию значение 'replace', чтобы ошибки легко обнаруживались. Может быть полезно установить его на 'strict', чтобы поймать ошибку и сообщить о плохих данных клиенту.

Объекты запроса и ответа

Поскольку объекты запроса и ответа обычно являются центральными элементами приложений, использующих Werkzeug, вы можете изменить кодировку по умолчанию, на которой работает Werkzeug, путем наследования этих двух классов. Например, вы можете легко установить приложение на utf-7 и строгую обработку ошибок:

from werkzeug.wrappers import BaseRequest, BaseResponse

class Request(BaseRequest):
    charset = 'utf-7'
    encoding_errors = 'strict'

class Response(BaseResponse):
    charset = 'utf-7'

Обратите внимание, что обработка ошибок настраивается только для всех декодировок, но не для кодирования. Если Werkzeug обнаруживает ошибку кодирования, будет поднято исключение UnicodeEncodeError. Вам нужно убедиться, что создаваемые данные присутствуют в целевом наборе символов (это не проблема для всех кодировок юникода, таких как utf-8).

Файловая система

Изменено в версии 0.11.

До версии 0.11 Werkzeug использовал функциональность стандартной библиотеки Python для определения кодировки файловой системы. Однако несколько отчетов об ошибках в отношении Werkzeug показали, что значение sys.getfilesystemencoding() нельзя доверять в традиционных системах UNIX. Обычные проблемы возникают из-за неправильно настроенных систем, где LANG и аналогичные переменные среды не установлены. В таких случаях Python по умолчанию устанавливает кодировку файловой системы на ASCII, что является очень консервативным значением по умолчанию, которое обычно неверно и создает больше проблем, чем решает.

Поэтому Werkzeug принудительно установит кодировку файловой системы на UTF-8 и выдаст предупреждение всякий раз, когда обнаружит, что работает под BSD или Linux, и sys.getfilesystemencoding() возвращает кодировку ASCII.

См. также werkzeug.filesystem.

© 2007–2020 Pallets
Licensed under the BSD 3-clause License.
https://werkzeug.palletsprojects.com/en/0.16.x/unicode/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API