Думаю, самый первый отличный момент, что 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
Вот, что удивляет, так это проблемы с 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
При использовании 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
Дык, схема то простая. Но вот например библиотеки парсинга XML и/или x/HTML, которым просто удобнее было бы взаимодействовать с юникодными данными, поголовно требуют на вход обычные строки. Хотя внутри работают в юникоде.
Comment by Dmitry Vasiliev on 15:00, 2009 1 25
В стандартной библиотеке все для обработки XML возвращает для текстовых данных Unicode, так что не знаю. В XML с этим жестко, хотя я видел пару примеров когда без указания явной кодировки в XML пытались запихивать текст в CP1251. :-)
А вот с HTML все сложнее, т.к. во многих случаях кодировка HTML документа существует только в контексте HTTP протокола. Так что тут зависит от конкретной библиотеки.
Comment by goodguy on 21:47, 2009 1 25
Стандартная для 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
Димка, представляешь, я таки начал писать на Питоне. Не на 3.0, правда, но начал. Как ты и обещал - куча положительных эмоций :).
Comment by Dmitry Vasiliev on 12:36, 2009 1 26
> Стандартная для 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
> Димка, представляешь, я таки начал писать на Питоне. Не на 3.0, правда, но начал. Как ты и обещал - куча положительных эмоций :).
Круто. :-) С Python 3 собственно и не надо пока начинать.
Add comment