Разработка на Python: i18n
Пояснение. Изначально я собирался описывать конкретные особенности TurboGears, но понял что текст получается большой и достаточно общий и решил разбить его на две части. В этой части пойдет речь о Python вообще, а в следующей — о TurboGears в частности.
Итак, о создании «интернационализированных» (уф!) приложений на Python.
Основные компоненты этой системы:
- поддержка национальных (местных) особенностей: сортировка с учетом национального алфавита, представление дат и чисел и прочее, модуль locale;
- локализация приложений: перевод сообщений на разные языки, модуль gettext;
- поддержка различных форматов кодирования текста: фактически сводится к поддержке стандарта Unicode, различных кодировок (Latin-1, UTF-8, WIN1251) и преобразований текста из одной кодировки в другую.
>>> ut = 'тест'.decode('cp1251') >>> print repr(ut) u'u0442u0435u0441u0442' >>> print repr(ut.encode('utf-8')) 'xd1x82xd0xb5xd1x81xd1x82'Пояснение: я использовал cp1251 т.к. эта кодировка, которую использует IDLE на платформе Windows.
Главная особенность Python в отличии от, скажем, Java: различие между обычными строками (str) и юникодными (unicode). При выводе юникодные строки можно отличить по букве u перед строкой, а программно — при помощи функций isinstance() или type().
Кому-то такое разделение нравится, кому-то нет, но про него всегда следует помнить, в противном случае вы рискуете получить UnicodeEncodeError в самом неожиданном месте:
>>> str(ut) Traceback (most recent call last): ... UnicodeEncodeError: 'ascii' codec can't encode characters ... >>> print type(ut), type(ut.encode('cp866'))Эта ошибка произошла из-за того, что функция str пытается преобразовать юникодную строку в обычную, но используя неподходящую кодировку (ascii). И ошибку такую получить достаточно легко, благо str() или __str__() вызывается часто неявно, e.g.: print.
Отсюда первое и главное правило работы с юникодом на Питоне: чтобы не запутаться с кодировками, используйте только юникодные строки внутри программы и перекодируйте текст для ввода/вывода.
Правило простое и практически на 100% надежное. «Практически» — потому что некоторые библиотеки (в т.ч. из stdlib) могут некорректно обрабатывать юникодные строки, так что при использовании внешних библиотек следует быть внимательным. К счастью, такое встречается все реже а, скажем, некоторые DB-API драйверы (psycopg) уже научились принимать и отдавать юникодные строки.
Да, для ASCII-текста можно использовать юникодные строки, а можно продолжать пользоваться обычными: т.к. неявные преобразования используют кодировку ’ascii’ вы гарантированно не получите UnicodeEncodeError. Еще одно отступление: в принципе, можно заставить Python использовать другую кодировку вместо ascii при помощи site.setencoding() или sitecustomize но я так не делаю и не советую.
Есть и библиотечные модули, ориентированные на работу с юникодным текстом. Например, модуль codecs позволяет легко огранизовать чтение/запись файлов:
>>> for line in codecs.open(fname, 'r', 'utf-8'): ... assert isinstance(line, unicode) >>>
Немає коментарів
Підписатись на коментаріВідписатись від коментарів Коментарі можуть залишати тільки користувачі з підтвердженими акаунтами.