Подготовка преобразовать от Python 2.x до 3.x

Как все мы знаем к настоящему времени (я надеюсь), Python 3 медленно начинает заменять Python 2.x. Конечно, это будут много ЗА МНОГИЕ годы до того, как большая часть существующего кода будет наконец портирована, но существуют вещи, которые мы можем сделать прямо сейчас в нашем коде версии 2.x для переключений легче.

Очевидно, взгляд на новые функции и возможности в 3.x будет полезен, но каковы некоторые вещи, которые мы можем сделать прямо сейчас, чтобы сделать предстоящее преобразование более безболезненным (а также помочь произвести обновления параллельных версий в случае необходимости)? Я конкретно думаю о строках, мы можем начать наши сценарии с этим, сделает более ранние версии Python более подобными 3.x, хотя другие привычки также приветствуются.

Самый очевидный код, чтобы добавить к верхней части сценария, что я могу думать:

from __future__ import division
from __future__ import print_function
try:
    range = xrange
except NameError:
    pass

Самая очевидная вещь привычки, о которой я могу думать, "{0} {1}!".format("Hello", "World") для строкового форматирования.

Какие-либо другие строки и хорошие привычки войти?

11
задан Wayne Werner 6 August 2010 в 13:36
поделиться

2 ответа

Самая большая проблема, которую нельзя адекватно решить с помощью изменений на микроуровне и 2to3, - это изменение типа строки по умолчанию с байтов на Unicode.

Если вашему коду нужно что-то делать с кодировками и байтовым вводом-выводом, для правильного преобразования потребуется много ручных усилий, чтобы вещи, которые должны быть байтами, оставались байтами и соответствующим образом декодировались на нужном этапе. . Вы обнаружите, что некоторые строковые методы (в частности format () ) и вызовы библиотек требуют строк Unicode, поэтому вам могут потребоваться дополнительные циклы декодирования / кодирования только для использования строк как Unicode, даже если они действительно просто байты.

Этому не способствует тот факт, что некоторые модули стандартной библиотеки Python были грубо преобразованы с использованием 2to3 без должного внимания к вопросам байтов / юникода / кодирования, и поэтому сами ошибаются в выборе подходящего типа строки. Некоторые из них сейчас решаются, но, по крайней мере, с Python 3.0 до 3.2 вы столкнетесь с запутанным и потенциально ошибочным поведением таких пакетов, как urllib, email и wsgiref, которым необходимо знать о байтовых кодировках.

Вы можете решить проблему, если будете осторожны каждый раз, когда пишете строковый литерал. Используйте строки u '' для всего, что изначально является символьным, b '' строки для всего, что действительно байтами, и '' для «строки по умолчанию» type, где это не имеет значения, или вам нужно соответствовать требованиям к использованию строки библиотечного вызова.

К сожалению, синтаксис b '' был введен только в Python 2.6, поэтому это отсекает пользователей более ранних версий.

эта:

какая разница?

О боже. Что ж ...

Байт содержит значение в диапазоне 0–255 и может представлять загрузку двоичных данных (например, содержимое изображения) или некоторого текста, и в этом случае должен быть выбран стандарт о том, как отобразить набор символов в эти байты. Большинство этих стандартов «кодирования» отображают обычный набор символов «ASCII» в байты 0–127 таким же образом, поэтому в целом безопасно использовать байтовые строки для обработки текста только в формате ASCII в Python 2.

Если вы хотите использовать любой из символов вне набора ASCII в байтовой строке, у вас проблемы, потому что каждая кодировка отображает другой набор символов в оставшиеся байтовые значения 128–255, и большинство кодировок могут ' t отображать все возможные символы в байты. Это источник всех тех проблем, когда вы загружаете файл из одной локали в приложение 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. Для персонажей в Basic Multilingual Plane от 0x0000–0xFFFF вы не заметите никакой разницы, но если вы используете символы вне этого 16-битного диапазона, те, которые находятся в «астральных планах», вы обнаружите, что они принимают два юнита вместо одного, и, опять же, вы рискуете разделить персонажа, разрезая их.

Это довольно плохо, и произошло потому, что Windows (и другие, такие как Java) остановились на UTF-16 в качестве механизма хранения в памяти до того, как Unicode превысил ограничение в 65 000 символов. Тем не менее, использование этих расширенных символов по-прежнему довольно редко, и любой пользователь Windows будет привыкать к их взлому во многих приложениях, поэтому для вас это, вероятно, не критично.

В «широких сборках» строки Unicode состоят из единиц «кодовой точки» реальных символов, поэтому даже расширенные символы вне BMP могут обрабатываться последовательно и легко. Плата за это - эффективность: каждая строковая единица занимает четыре байта в памяти.

12
ответ дан 3 December 2019 в 07:10
поделиться

Я пытаюсь взять в привычку использовать вещи вроде var1//var2 всякий раз, когда мне действительно нужно целочисленное деление (а не float). Это не большой шаг к Python 3, но по крайней мере мне не придется возвращаться и проверять все свои деления :)

5
ответ дан 3 December 2019 в 07:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: