LINUX.ORG.RU

[python] Gtk + Utf8 + Unicode <- живут в дружбе и мире благодаря грязному Хаку?

 


0

1

рассказываю всё попорядку:

Глава 1. введение::

из чтения документаций — заметил что в Gtk-фреймворке в принцепе в основном используются байтовые строки (а не Unicode-строки)

....однако Unicode`ные строки тоже хорошо работают... (все Gtk-функции их свободно «понимают» )

тоесть оба варианта работают и официально щитаются корректными:

my_text_entry_1.set_text(  b'байтовая строка'  )
my_text_entry_2.set_text(  u'юникодная строка'  )
Глава 2. слегка необычное удобство::

однако можно делать даже так (!):

# даже в случае не-ascii символов в GTK-строке -- свободно извлекается юникодный объект:
unistr = unicode(my_text_entry.get_text()) # хотя ОБЫЧНО -- в Python-2 (в отличии от Python-3) это делать нельзя, 
                                           # без явного указания кодировки. (например xxxx.decode('UTF-8') )
этот блок текста мне показался немного НЕОБЫЧНЫМ — ведь для преобразования между Байтовой-Строкой <=> Юникодной-строкой — обычно как-раз используется функция-конвертирования в которой в качестве аргумента фигурирует имя кодировки..

и праграммист должен ТОЧНО (на 100%) ЗНАТЬ — какая конкретно кодировка имеется ввиду.

например для кодирования НАЗВАНИЯ файлов используется одна кодировка, а для кодированиях СОДЕРЖАНИЯ файлов — другая кодировка . для кодирования символов ТЕРМИНАЛА используется третья кодировка .. вобщем — для каждой сущности в операционной системе — как правило существует своя кодировка... некоторые кодировки в различных операционных системах повторяются (например кодировка не-юникодного GUI в Windows совпадает с кодировкой содержимого текстовых файлов (но эта кодировка отличается от кодировки имён файлов и кодировки терминала) .. в других операционных системах схожести и различия могут быть другие...

...так-что каждый программист который пишет кросплатформенную программу должен везде (для каждой сущности) — использовать специальную кодировку название которой — извлекается через ту-или-иную _соответствующщую_ спец-функцию (а не вбивается через исходный код) .

[[[[ вобщем головная боль с названиями кодировок :-) . можно сделать баг и никогда в жизне его не заметить, так как проявлятсья он будет на фиг пойми какой операционной системе, в фиг-пойми какой языковой группе ]]]]

но если GTK не требует указывать кодировку для своих Виджетов при оперировании Юникодными объектами — то значит с программиста сподает очередная головная боль .. программисту не придётся задумываться над вопросом: «а верно ли я понимаю какую я должен использовать кодировку для GTK-виджетов»

Глава 3. необычность выходит за рамки Gtk::

оказывается что в Gtk программах рабтает даже ЭТО(!!!):

unistr = u'внутри юникодной строки -- %s . вот так-то!' % b'байтовая строка'
btstr = b'внутри байтовой строки -- %s . вот так-то!' % u'юникодная строка'
# привет миру Python-3 -- где такое возможно "из-коробки" :-) , для любых программ
так-так.... попахивает грязным хаком, который исправляет поведение целого Пайтона при использовании GTK

Глава 4. а вот тут — хак таки-пойман с поличным::

простая Пайтон-программа из четырйх строчек:

import sys
print sys.getdefaultencoding() # печатает: ascii
import gtk
print sys.getdefaultencoding() # печатает: utf-8

вот оказывается почему (изза этого хака) — так свободно PyGTK оперирует с Юникодными-строками... тоест ьпо сути поддержки юникодных строк в PyGTK — нет :-( :-(

[и вместо того чтобы переписать все PyGTK-функции из Байтовых-строк на Юникодные-строки, разработчики решили просто сделать — ЭТО]

Глава 5. эпилог::

что думаете про всё это? :-)

***

и вот ещё вопрос — как они реализовали этот «хак» ? ведь функция sys.setdefaultencoding(...) [ http://j.mp/92lnL6 ] — не работает %) %)

былобы полезно заюзать этот хак и не в GTK-программах :-)

(GTK не изменяет указатель на функцию sys.getdefaultencoding .. — это проверял )

Python 2.6.6 (r266:84292, Sep 15 2010, 15:52:39) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> enc = sys.getdefaultencoding
>>> enc()
'ascii'
>>> import gtk
>>> enc()
'utf-8'
>>>

Ответ на: комментарий от true_admin

...но спасибо большое за приведённый пример!

теперь я не буду рахваливать Python3 как супер-универсально решение, в котором (в отличии от Python-2) теперь можно перестать думать головой :-) :-)

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от Legioner

> А чем плох UTF-8, лежащий в байтовом массиве, для хранения и

обработки строк?


для целей _хранения_ и _передачи_ — UTF-8 совсем не плох... (его и польуют в этом случае :-) :-))

но для _обработки_ — мне намного удобнее когда обрабатываемый массив содержит тот уровень абстракции — который больше подходит к моему «слоёному пирогу» :-) ..

[тоесть в если «слоёном пироге» какие-то «строчки текста» то логично что их элементы этох «строчек текста» — должны быть «символы текста» а не «байты»]

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от user_id_68054

Ну в общем мой point в том, что при обработке UTF-8 строк их приходится трактовать как связный список. Отсутствует возможность обращаться к i-му символу за O(1). И вроде как сразу становится неудобно. Но на самом деле мало алгоритмов на строках, которые именно требуют такую адресацию. Чаще всего вполне хватает перебора в стиле итератора.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

Не люблю привязываться к незначительным мелочам, но хотелось бы до конца прояснить ситуацию.

O(n) в чистом виде при обращении к элементам unicode-буфера в python будет только в том случае, когда в my_unicode[start:stop:step], step != 1, т.е. когда нужно брать элементы не подряд.

В python, внутренний формат хранения Unicode - UCS2 (или UCS4), т.е. все элементы имеют один размер. Обращение к ним (то, что вы называете «возможность обращаться к i-му символу»), соответственно, O(1).

Для выборки подстроки с шагом 1 применяется memcpy, а не поэлементное копирование.

shylent
()
Ответ на: комментарий от Legioner

> ... Но на самом деле мало алгоритмов на строках, которые именно требуют такую адресацию. Чаще всего вполне хватает перебора в стиле итератора.

я впринцепе в определённой мере — согласен с вами, нащёт того что utf-8 ну практически пригоден для широко-потребительского использования

(ну подумаешь что труднее будет реализовать операцию «показывать только первые 200 символов (не байтов) — от всего текста» ...
..и всего делов-то.. в остальном-то ведь utf8-строчки вполне неприхотливы :-))

например если бы я использовал бы для программирования — низкоуровневые языки такие как C/C++ — то тогда бы я даже наверно не задумываясь ни о чом — использовал бы в своих программах utf8-строчки :-)

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от user_id_68054

_разные_ программы..

именно, их и сравниваем. Нет смысла сравнивать одинаковые программы.

в Python-2 — строковая константа — была байтовой, но в Python3 вы уже зачемто решили вывести на экран юникодную строковую константу...

Да, тупанул. В py2 та же фигня вылазит. Херово это всё. Приходится костыли сажать, притом явно не документированно.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

верно.. хренова ... :-( ...

а почему «костыли» — не документированно? :-) :-)

ведь если добавить комментарии/doc-строки к «костылям» наподобие вот этих — http://www.linux.org.ru/jump-message.jsp?msgid=5454970&cid=5456898 — то «костыли» станут документированными :-)

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от true_admin

кстате говоря — если разработчики щитают что функция «print()» должна либо печатать «ровно-в-ровно как надо» либо вылетать с ошибкой

 — то я не вижу в этом особого маразма :-)

[да.. хренова.... но всё же НЕ маразм :-) ]

....по хорошему — архитекторам Пайтона — думаю надабыло просто-навсего сделать _две_ разные функции «print(..)» [встроенные. так как невстроенные можно и самому сделать]

второй вид функции «print(..)» — как раз такую чтобы она могла печатать «примерно то что её просят», но не вылетать с ошибкой

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от true_admin

> Кстати, эта проблема исправляется, например, так: sys.stdout = codecs.getwriter(«utf-8»)(sys.__stdout__)

и создаётся куча новых проблемм (в отличии от http://www.linux.org.ru/jump-message.jsp?msgid=5454970&cid=5456898 )...

например то как оно будет работать в Терминале Windows :-)

но вообще идея использовать codecs.getwriter(..) — думаю довольно зачётная! спасибо!... этот объект видимо хорошо бы использовать для реально высококачественных «хаков» :-)

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от user_id_68054

мда, я подумал и решил что наверно оно так и правильно, но всё же хотелось бы видеть упор на это в доках. Только мне щас не до писанины, может потом напишу.

Кстати, щас посмотрел у себя, /etc/default/locale у мну utf8 в дефолте, так что мне это не актуально. Надеюсь скоро забуду о не-utf8 терминалах как о страшном сне.

как оно будет работать в Терминале Windows :-)

пох :).

true_admin ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.