Самая большая проблема, которую нельзя адекватно решить с помощью изменений на микроуровне и 2to3, — это изменение типа строки по умолчанию с байтов на Unicode.
Если вашему коду нужно что-то делать с кодировками и байтовым вводом-выводом, потребуется куча ручных усилий для правильного преобразования, чтобы вещи, которые должны быть байтами, оставались байтами и декодировались соответствующим образом на нужном этапе. Вы обнаружите, что некоторые строковые методы (в частности, format()) и библиотечные вызовы требуют строк Unicode, поэтому вам могут потребоваться дополнительные циклы декодирования/кодирования только для использования строк как Unicode, даже если они на самом деле просто байты.
Этому не способствует тот факт, что некоторые модули стандартной библиотеки Python были грубо преобразованы с использованием 2to3 без должного внимания к проблемам с байтами/юникодом/кодировкой, и поэтому сами делают ошибки в отношении того, какой тип строки подходит. Кое-что из этого еще прорабатывается, но, по крайней мере, с Python 3.0 до 3.2 вы столкнетесь с запутанным и потенциально ошибочным поведением таких пакетов, как urllib, email и wsgiref, которым нужно знать о кодировках байтов.
Вы можете решить проблему, проявляя осторожность каждый раз, когда пишете строковый литерал. Используйте строки u'' для всего, что по своей сути основано на символах, строки b'' для всего, что действительно состоит из байтов, и '' для типа «строки по умолчанию», когда это не имеет значения или вам нужно соответствовать требованиям к использованию строки библиотечного вызова.
К сожалению, синтаксис b'' был введен только в Python 2.6, поэтому это отключает пользователей более ранних версий.
эта:
какая разница?
О боже. Что ж...
Байт содержит значение в диапазоне 0–255 и может представлять собой загрузку двоичных данных (например, содержимое изображения) или некоторый текст, и в этом случае должен быть выбран стандарт для отображения набора символов в эти байты. Большинство этих стандартов «кодирования» таким же образом отображают обычный набор символов «ASCII» в байты 0–127, поэтому обычно безопасно использовать байтовые строки для обработки текста только в ASCII в Python 2.
Если вы хотите использовать любой из символов вне набора ASCII в строке байтов, у вас проблемы, потому что каждая кодировка отображает другой набор символов в оставшиеся значения байтов 128–255, а большинство кодировок не могут отображать каждый возможный символ в байты. Это источник всех тех проблем, когда вы загружаете файл из одной локали в приложение Windows в другой локали, и все акцентированные или нелатинские буквы меняются на неправильные, создавая нечитаемый беспорядок. (он же «моджибаке».)
Существуют также «многобайтовые» кодировки, которые пытаются вместить больше символов в доступное пространство, используя более одного байта для хранения каждого символа. Они были введены для регионов Восточной Азии, так как китайских иероглифов очень много. Но есть также UTF-8, улучшенная современная многобайтовая кодировка, которая может вместить каждый символ.
Если вы работаете с байтовыми строками в многобайтовой кодировке — а сегодня, вероятно, так и будет, потому что UTF-8 очень широко используется; на самом деле никакая другая кодировка не должна использоваться в современном приложении — тогда у вас будет еще больше проблем, чем просто отслеживание того, с какой кодировкой вы играете. len() будет сообщать вам длину в байтах, а не длину в символах, и если вы начнете индексировать и изменять байты, вы, скорее всего, разорвете многобайтовую последовательность на две части, создав недопустимую последовательность и вообще все запутаете.
По этой причине Python 1.6 и более поздние версии имеют собственные строки Unicode (обозначаются как u'something'), где каждая единица в строке является символом, а не байтом. Вы можете len() их резать, заменять, заменять, использовать регулярные выражения, и они всегда будут вести себя соответствующим образом. Для задач обработки текста они, несомненно, лучше, поэтому Python 3 делает их строковым типом по умолчанию (без необходимости ставить u перед '').
Загвоздка в том, что многие существующие интерфейсы, такие как имена файлов в операционных системах, отличных от Windows, или HTTP, или SMTP, в основном основаны на байтах с отдельным способом указания кодировки. Поэтому, когда вы имеете дело с компонентами, которым нужны байты, вы должны позаботиться о том, чтобы правильно кодировать ваши строки Unicode в байты, а в Python 3 вам придется делать это явно в некоторых местах, где раньше вам это не нужно.
Это внутренняя деталь реализации, заключающаяся в том, что строки Unicode занимают «два байта» памяти на внутреннюю единицу. Вы никогда не увидите это хранилище; вы не должны думать об этом с точки зрения байтов. Единицы, над которыми вы работаете, концептуально являются символами, независимо от того, как Python выбирает для их представления в памяти.
...в стороне:
Это не совсем так. В «узких сборках» Python, таких как сборка Windows, каждая единица строки Unicode технически является не символом, а «единицей кода» UTF-16. Для символов на Основном многоязычном плане в диапазоне от 0x0000 до 0xFFFF вы не заметите никакой разницы, но если вы используете символы за пределами этого 16-битного диапазона, то есть те, что находятся на «астральных планах», вы обнаружите, что они принимают две единицы вместо одной, и, опять же, вы рискуете разделить персонажа, когда будете их нарезать.
Это довольно плохо, и произошло потому, что Windows (и другие, такие как Java) остановились на UTF-16 в качестве механизма хранения в памяти до того, как Unicode превысил ограничение в 65 000 символов. Тем не менее, использование этих расширенных символов все еще довольно редко, и любой пользователь Windows привыкнет к тому, что они ломаются во многих приложениях, поэтому для вас это, вероятно, не критично.
В «широких сборках» строки Unicode состоят из единиц «кодовой точки» реальных символов, поэтому даже расширенные символы за пределами BMP могут обрабатываться последовательно и легко. Платой за это является эффективность: каждая единица строки занимает четыре байта в памяти.
person
Community
schedule
06.08.2010