python

Python 3.0 и напильник

Dmitry Vasiliev 17:00, 2009 1 19

Уже прошло больше месяца как вышел Python 3.0. В меру своего свободного времени мне удалось с ним повозиться и можно описать первые впечатления.

Думаю, самый первый отличный момент, что Python 3.0 не встретился в пространстве состояний с Perl 6 и Duke Nukem Forever. ;-) Конечно, вряд ли стоит ожидать, что самая первая версия, включающая в себя такое количество изменений, будет идеальной и я бы рассматривал версию 3.0 как очередную бэта-версию, хотя выпуск ее как основного релиза очень важен.

Скорее всего основной проблемой при миграции на Python 3 будет переход к Unicode (хотя многие сетовали на превращение print в функцию, но для меня это не стало камнем преткновения :-). Вот несколько моментов:

  • Еще перед релизом я открыл четыре тикета для imaplib, telnetlib, nntplib и poplib. Все четыре модуля не работали из-за перехода к Unicode. Я даже начал делать патчи с преобразованием к Unicode, но, в итоге, от этого отказались и все привели к bytes.
  • После релиза я столкнулся с тем, что модуль wsgiref тоже не работает из-за перехода к Unicode. При этом работа над патчем осложнялась тем, что это реализация стандарта WSGI и Phillip J. Eby (PJE) сначала сильно противился переходу к bytes, т.к. стандарт явно говорит об использовании str и требовал обсуждения в рассылке wsgi-sig. В итоге, когда я написал в рассылку мне сразу же указали на давно принятые поправки к стандарту в которых PJE принимал непосредственное участие. PJE сослался на то, что он занят написанием книги и обо всем забыл и wsgiref наконец удалось исправить. :-)
  • bytes в Python 3 - это не совсем тоже, что str в Python 2. Он не имеет многих методов которые использовались для строк, возвращает при итерировании целые числа и соответственно его теперь нельзя так же просто обменивать с str как можно было обменивать unicode/str в Python 2;
  • Утилита 2to3 по-умолчанию преобразует str из Python 2 в str в Python 3 (который соответствует unicode из Python 2). Боюсь, что здесь возможен ряд интересных эффектов которые сложно предусмотреть заранее;
  • Похоже что в стандартной библиотеке Python 3.0 пока не сформировались стандартные подходы к тому, где использовать str, а где bytes и где преобразовывать одно в другое. Например, теперь urllib.parse.unquote() преобразует результат к str, но когда эта функция вызывается, например, из urllib.parse.parse_qsl() кодировку указать нельзя.

Кроме этого большого момента отметил для себя пару интересных мелочей:

  • open() теперь может принимать дескриптор открытого файла.
  • модуль codecs теперь использует объект CodecInfo для описания кодировок.

Comments All comments

Comment by goodguy on 23:26, 2009 1 24

goodguy's Gravatar

Вот, что удивляет, так это проблемы с Unicode. У меня они начались ещё в версии 2.4 когда увидел бардак в том, как та же urllib обрабатывает строки и может вернуть равно str равно и unicode. А потом возникает проблема сопряжений, когда выход из одного процесса идёт в unicode, а вход следующего требует str, а параллельно запускается ещё один процесс, принимающий unicode. В итоге кучи костылей, приводящих выход к unicode и проверки методом тыка что способен понять каждый метод. При отсутствии конструкций вроде (expression ? true_expression : false_expression) это увеличивает кол-во бестолковых строк, и в-общем приводит к некоторой нечитаемости кода.

Comment by Dmitry Vasiliev on 13:48, 2009 1 25

Dmitry Vasiliev's Gravatar

При использовании Unicode есть одна простая схема:

- Все текстовые данные внутри процесса должны быть в Unicode.

При этом входящие данные преобразуются ИЗ соотв. кодировок и выходящие преобразуются В соотв. кодировки. Если все это дело собственной разработки, то надо использовать кодировки которые могут передавать весь диапазон Unicode, например UTF-8, UTF-16 и т.п.

Больше всего проблем обычно возникает когда имеешь дело с каким-то криво разработанным внешним протоколом (или системой). Например с NNTP пока полный бардак - в новом RFC 3977 уже говорят про UTF-8, а по факту пока используется RFC 977 где все должно быть в US-ASCII (собственно тогда и Unicode еще не родился :). В итоге, в группах fido7.* все в основном в KOI-8R, а где-то может и UTF-8 проскочить, или CP1251. И создание какого-нить индексатора становится уже не тривиальной задачей.

Comment by goodguy on 13:59, 2009 1 25

goodguy's Gravatar

Дык, схема то простая. Но вот например библиотеки парсинга XML и/или x/HTML, которым просто удобнее было бы взаимодействовать с юникодными данными, поголовно требуют на вход обычные строки. Хотя внутри работают в юникоде.

Comment by Dmitry Vasiliev on 15:00, 2009 1 25

Dmitry Vasiliev's Gravatar

В стандартной библиотеке все для обработки XML возвращает для текстовых данных Unicode, так что не знаю. В XML с этим жестко, хотя я видел пару примеров когда без указания явной кодировки в XML пытались запихивать текст в CP1251. :-)

А вот с HTML все сложнее, т.к. во многих случаях кодировка HTML документа существует только в контексте HTTP протокола. Так что тут зависит от конкретной библиотеки.

Comment by goodguy on 21:47, 2009 1 25

goodguy's Gravatar

Стандартная для 3.0? Там возможно и хорошо всё, не спорю. Но 2.4 и 2.5 на вход хотят str, так что приходится делать encode('utf-8').

А если потребуется парсинг не всегда корректно сформатированного HTML - рекомендую http://code.google.com/p/html5lib/ - очень удобная библиотека как для парсинга, так и для загона обратно в html. Что удобно - можно получать DOM дерево и работать с ним как с XML, а потом получать корректный HTML :)

Comment by StoneWolf on 23:03, 2009 1 25

StoneWolf's Gravatar

Димка, представляешь, я таки начал писать на Питоне. Не на 3.0, правда, но начал. Как ты и обещал - куча положительных эмоций :).

Comment by Dmitry Vasiliev on 12:36, 2009 1 26

Dmitry Vasiliev's Gravatar

> Стандартная для 3.0? Там возможно и хорошо всё, не спорю. Но 2.4 и 2.5 на вход хотят str, так что приходится делать encode('utf-8').

Не, погоди - на входе и должен быть набор байтов (соотв. str в Python 2 и bytes в Python 3) т.к. например, для XML ты не знаешь кодировки до начала обработки.

> А если потребуется парсинг не всегда корректно сформатированного HTML

Думаю пока самая рулезная либа для этого - это BeautifulSoup (http://www.crummy.com/software/BeautifulSoup/)

Comment by Dmitry Vasiliev on 12:38, 2009 1 26

Dmitry Vasiliev's Gravatar

> Димка, представляешь, я таки начал писать на Питоне. Не на 3.0, правда, но начал. Как ты и обещал - куча положительных эмоций :).

Круто. :-) С Python 3 собственно и не надо пока начинать.

Add comment

Name:
Email: (Never will be published.)
Web site:
Comment: (Paragraphs divided by empty lines, line breaks and links will be automatically formatted.)