Новичок
Профиль
Группа: Участник
Сообщений: 3
Регистрация: 21.3.2009
Репутация: нет Всего: нет
|
я учусь писать прогараммы на питоне и вот мне пришлось использовать питон 2.6 а не 3.0 т.к. многие библиотеки ещё не пересобраны. Как и следовало ожидать, я столнулся с проблемой кодировок. в 2.6: Код | # -*- coding: utf-8 -*- >>> list1 = ["этот", "тот", ["он", "другой"]] >>> list2 = ['пока', 'привет'] >>> list1 ['\xd1\x8d\xd1\x82\xd0\xbe\xd1\x82', '\xd1\x82\xd0\xbe\xd1\x82', ['\xd0\xbe\xd0\xbd', '\xd0\xb4\xd1\x80\xd1\x83\xd0\xb3\xd0\xbe\xd0\xb9']] >>> list2 ['\xd0\xbf\xd0\xbe\xd0\xba\xd0\xb0', '\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82'] >>> print list1 ['\xd1\x8d\xd1\x82\xd0\xbe\xd1\x82', '\xd1\x82\xd0\xbe\xd1\x82', ['\xd0\xbe\xd0\xbd', '\xd0\xb4\xd1\x80\xd1\x83\xd0\xb3\xd0\xbe\xd0\xb9']] >>> print list2 ['\xd0\xbf\xd0\xbe\xd0\xba\xd0\xb0', '\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82'] >>>
|
надо заметить что в 3.0 этот код прекрасно работает(ещё как(!!!)): Код | # -*- coding: utf-8 -*- >>> list1 ['этот', 'тот', ['он', 'другой']] >>> list2 ['пока', 'привет'] >>> print(list1) ['этот', 'тот', ['он', 'другой']] >>> print(list2) ['пока', 'привет']
|
Спросил на форуме наткнулся только на возмущенные советы читать гугл. Делать было нечего и в течении нескольких дней я, как прилежный мальчик читал интернеты, тысячи их. И вот что я понял: Все проблемы возникают от того что исполняемый код поставляет поток байтов в выходной поток, а выходной поток отображается в терминальное окно, но так как индетификатор потока никак не передаётся, то терминальное окно читает поток в той кодировке, которая в нём установленна. Как оказалось кодировку терминала можно определить вызовом Код | >>> import sys >>> sys.stdout.encoding |
Интересно что для командной строки питона 2.6 это cp866 для шелла питона 2.6 это cp1251 для командной строки питона 3.0 это cp866 а для питона шелла cp1251 (а что кстати делате такой вызов locale.getpreferredencoding() и в чём его отличие от sys.stdout.encoding?) В роде разобрались в чём проблема.... в 2.6 не иначе. Что делать? Я прочитал и попробовал множество разных способов ни один меня полностью не удовлетворил. Далее в произвольном порядке(Все ниже сказанное относиться только к питону 2.6, т.к в 3.0 этой проблемы не возникает(или у меня пока не возникло)) Сразу договоримсячто все коды я хочу по православному писать в utf-8 т.е. кодировку всех файлов я устанавливаю как utf-8 и в начале каждого файла пишу Код | # -*- coding: utf-8 -*- |
? таким образом яна шаг приближаюсь к созданию интернациональных приложений. способ 1 "явное указание кодировки и преобразование при выводе" http://forum.script-coding.info/viewtopic.php?id=845 код: Код | # -*- coding: utf-8 -*- print '1 ' 'привет мир'
print '2 ' u'Привет, Мир!'
y=['он','она',['они','оно']] print '3', y
k=[u'он',u'она',[u'они',u'оно']] print '4', k
|
ответ: Код | >>> 1 привет РјРёСЂ 2 Привет, Мир! 3 ['\xd0\xbe\xd0\xbd', '\xd0\xbe\xd0\xbd\xd0\xb0', ['\xd0\xbe\xd0\xbd\xd0\xb8', '\xd0\xbe\xd0\xbd\xd0\xbe']] 4 [u'\u043e\u043d', u'\u043e\u043d\u0430', [u'\u043e\u043d\u0438', u'\u043e\u043d\u043e']] >>> |
как видно напечатать привет мир у нас уже получается, а вот список или словарь уже нет(((( способ 2 "обёртка для вывода"http://forum.script-coding.info/viewtopic.php?id=845 как я понимаю проблему, мы зададим окну вывода кодировку символьного потока. терминал будет читать из входного потока именно той кодировке, в которой мы туда будем символы отправлять. код: Код | # -*- coding: utf-8 -*- import codecs, sys outf = codecs.getwriter('cp1251')(sys.stdout, errors='replace') sys.stdout = outf print >> outf, u'Первый пошёл!' print u'Второй пошёл!' outf.write(u'Третий пошёл!\n')
#print '0 ' 'Привет, Мир!' ошибка
print '1 ' u'Привет, Мир!'
y=['он','она',['они','оно']] print '2', y
k=[u'он',u'она',[u'они',u'оно']] print '3', k
print >> outf,'4', k
#outf.write(k) ошибка #outf.write(y) ошибка
|
ответ Код | >>> Первый пошёл! Второй пошёл! Третий пошёл! 1 Привет, Мир! 2 ['\xd0\xbe\xd0\xbd', '\xd0\xbe\xd0\xbd\xd0\xb0', ['\xd0\xbe\xd0\xbd\xd0\xb8', '\xd0\xbe\xd0\xbd\xd0\xbe']] 3 [u'\u043e\u043d', u'\u043e\u043d\u0430', [u'\u043e\u043d\u0438', u'\u043e\u043d\u043e']] 4 [u'\u043e\u043d', u'\u043e\u043d\u0430', [u'\u043e\u043d\u0438', u'\u043e\u043d\u043e']] >>> |
Можем улучшить этот код добавив автоматическое определение кодировки: Код | # -*- coding: utf-8 -*- import codecs, sys code=sys.stdout.encoding outf = codecs.getwriter(code)(sys.stdout, errors='replace') sys.stdout = outf print >> outf, u'Первый пошёл!' print u'Второй пошёл!' outf.write(u'Третий пошёл!\n')
#print '0 ' 'Привет, Мир!' ошибка
print '1 ' u'Привет, Мир!'
y=['он','она',['они','оно']] print '2', y
k=[u'он',u'она',[u'они',u'оно']] print '3', k
print '4', y
print >> outf,'4', k
print >> outf,'5', y
#outf.write(k) ошибка #outf.write(y) ошибка
|
ответ: Код | >>> Первый пошёл! Второй пошёл! Третий пошёл! 1 Привет, Мир! 2 ['\xd0\xbe\xd0\xbd', '\xd0\xbe\xd0\xbd\xd0\xb0', ['\xd0\xbe\xd0\xbd\xd0\xb8', '\xd0\xbe\xd0\xbd\xd0\xbe']] 3 [u'\u043e\u043d', u'\u043e\u043d\u0430', [u'\u043e\u043d\u0438', u'\u043e\u043d\u043e']] 4 ['\xd0\xbe\xd0\xbd', '\xd0\xbe\xd0\xbd\xd0\xb0', ['\xd0\xbe\xd0\xbd\xd0\xb8', '\xd0\xbe\xd0\xbd\xd0\xbe']] 4 [u'\u043e\u043d', u'\u043e\u043d\u0430', [u'\u043e\u043d\u0438', u'\u043e\u043d\u043e']] 5 ['\xd0\xbe\xd0\xbd', '\xd0\xbe\xd0\xbd\xd0\xb0', ['\xd0\xbe\xd0\xbd\xd0\xb8', '\xd0\xbe\xd0\xbd\xd0\xbe']] >>> |
Подведём промежуточный итог - нам до сих пор не получилось корректно вывести список, хотя мы нашли кучу способов для вывода "привет мир", ну чем не результат!? У меня такое подозрение, что единственный путь - писать самому функции которые выводили бы списки, словари, кортежди....... используя при этом явную перекодировку символов на входе программы и на выходе. а именно так: www.rupy.ru/static/files/07/02/12/rupyru2007-yurevich-unicode-thesis.pdf Способ 3 http://pythonini.livejournal.com/14325.htmlв теории всё просто: Код | # -*- coding: utf-8 -*- # Конечно в нормальной жизни этих коментариев тут нет # Загрузить кодеки и библиотеку локалей, установить дефолтную локаль согласно # переменной окружения LC_ALL. import locale, codecs; locale.setlocale(locale.LC_ALL, '') # Теперь в encoding положим текущая кодировку локали. encoding = locale.getlocale()[1] # Если кодировка не определилась - это винды. Там полюбому UTF-8 :) if not encoding: encoding = "utf-8" # Установим дефолтную локаль. Финт с ушами reload() нужен потому что разработчики # питона дюже умные и логично удаляют функцию setdefaultencoding при загрузке. # Оно в общем то логично, но я же умный. import sys;reload(sys);sys.setdefaultencoding(encoding) # Установили кодеки для вывода в потоки согласно распорядку. sys.stdout = codecs.getwriter(encoding)(sys.stdout, errors = "replace") sys.stderr = codecs.getwriter(encoding)(sys.stderr, errors = "replace")
|
на практике результаты этого способа очень сильно отличаются в командной строке в IDLE и в SciTE: в командной сторке: Код | Python 2.6.1 (r261:67517, Dec 4 2008, 16:51:00) [MSC v.1500 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import locale, codecs; locale.setlocale(locale.LC_ALL, '') 'Russian_Russia.1251' >>> encoding = locale.getlocale()[1] >>> import sys;reload(sys);sys.setdefaultencoding(encoding) <module 'sys' (built-in)> >>> sys.stdout = codecs.getwriter(encoding)(sys.stdout, errors = "replace") >>> sys.stderr = codecs.getwriter(encoding)(sys.stderr, errors = "replace") >>> print 'hellou world' hellou world >>> y=['он','она',['они','оно']] >>> y ['\xae\xad', '\xae\xad\xa0', ['\xae\xad\xa8', '\xae\xad\xae']] >>> print y ['\xae\xad', '\xae\xad\xa0', ['\xae\xad\xa8', '\xae\xad\xae']] >>> k=[u'он',u'она',[u'они',u'оно']] >>> k [u'\u043e\u043d', u'\u043e\u043d\u0430', [u'\u043e\u043d\u0438', u'\u043e\u043d\ u043e']] >>> print k [u'\u043e\u043d', u'\u043e\u043d\u0430', [u'\u043e\u043d\u0438', u'\u043e\u043d\ u043e']] >>> >>> t='привет тебе' >>> t '\xaf\xe0\xa8\xa2\xa5\xe2 \xe2\xa5\xa1\xa5' >>> print t ЇаЁў?в в?Ў? >>> print t.decode('utf-8')#в SciTE этот код работает' Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Python26\lib\encodings\utf_8.py", line 16, in decode return codecs.utf_8_decode(input, errors, True) UnicodeDecodeError: 'utf8' codec can't decode byte 0xaf in position 0: unexpecte d code byte >>> print t.decode('cp1251') ЇаЁў?в в?Ў? >>> print t.decode('cp866')# в SciTE это не работает привет тебе >>> print encoding 1251 >>> print u'привет' привет >>> sys.stdout.encoding 'cp866' >>> print type(sys.stdout.encoding) <type 'str'> |
в SciTE с установеленной строкой output.code.page=866 код: Код | # -*- coding: utf-8 -*- # Конечно в нормальной жизни этих коментариев тут нет # Загрузить кодеки и библиотеку локалей, установить дефолтную локаль согласно # переменной окружения LC_ALL. import locale, codecs; locale.setlocale(locale.LC_ALL, '') # Теперь в encoding положим текущая кодировку локали. encoding = locale.getlocale()[1] print encoding # Если кодировка не определилась - это винды. Там полюбому UTF-8 :) if not encoding: encoding = "utf-8" # Установим дефолтную локаль. Финт с ушами reload() нужен потому что разработчики # питона дюже умные и логично удаляют функцию setdefaultencoding при загрузке. # Оно в общем то логично, но я же умный. import sys;reload(sys);sys.setdefaultencoding(encoding) # Установили кодеки для вывода в потоки согласно распорядку. sys.stdout = codecs.getwriter(encoding)(sys.stdout, errors = "replace") sys.stderr = codecs.getwriter(encoding)(sys.stderr, errors = "replace")
print '1 ' u'Привет, Мир!'
y=['он','она',['они','оно']] print '2', y
k=[u'он',u'она',[u'они',u'оно']] print '3', k
print '4', y
#print >> outf,'5', y t='привет строка в юникод' h=u'привет юникод' h=t.decode('utf-8')
print type(h) print type(t) print t.decode('utf-8') print t.decode('cp866') print t.decode('cp1251') print u"принт" print k print sys.stdout.encoding print type(sys.stdout.encoding) |
ответ: Код | >pythonw -u "kodinglokal.py" 1251 1 Привет, Мир! 2 ['\xd0\xbe\xd0\xbd', '\xd0\xbe\xd0\xbd\xd0\xb0', ['\xd0\xbe\xd0\xbd\xd0\xb8', '\xd0\xbe\xd0\xbd\xd0\xbe']] 3 [u'\u043e\u043d', u'\u043e\u043d\u0430', [u'\u043e\u043d\u0438', u'\u043e\u043d\u043e']] 4 ['\xd0\xbe\xd0\xbd', '\xd0\xbe\xd0\xbd\xd0\xb0', ['\xd0\xbe\xd0\xbd\xd0\xb8', '\xd0\xbe\xd0\xbd\xd0\xbe']] <type 'unicode'> <type 'str'> привет строка в юникод ???А???????В ?Б?В?А?????? ?? ?О?????????? привет строка РІ СЋРЅРёРєРѕРґ принт [u'\u043e\u043d', u'\u043e\u043d\u0430', [u'\u043e\u043d\u0438', u'\u043e\u043d\u043e']] None <type 'NoneType'> >Exit code: 0 Time: 0.210 |
в IDLE код может и работает но так что ничего не видно. поток вывода проваливается куда-то....... полезная справка: setdefaultencoding(encoding) Устанавливает кодировку, которая будет использоваться по умолчанию при пре образовании обычных строк в строки Unicode и наоборот. Если строка encoding не соответствует доступной кодировке, генерирует исключение LookupError. Эта функция предназначена для использования в модуле site (или sitecustomize), после этого она обычно удаляется из пространства имен модуля sys. Функция доступна, начиная с версии 2.0. unicode(string [, encoding [, errors]]) Преобразует строку string из кодировки encoding (по умолчанию ’utf-8’) в строку Unicode и возвращает результат. Поведение при возникновении ошибок определяется значением аргумента errors: ’strict’ (используется по умолчанию) означает, что при возникновении ошибки будет сгенерировано исключение UnicodeError, ’ignore’ — недопустимые символы игнорируются (удаляются), ’replace’ — недопустимые символы заменяются универсальным символом замены (“REPLACEMENT CHARACTER”, u’\uFFFD’). LookupError Базовый класс исключений, генерируемых, если последовательность или отображение не содержит элемента с заданным индек- сом или ключом. Может быть сгенерировано напрямую функцией sys.setdefaultencoding(). sys.getdefaultencoding() Возвращает текущую кодировку, используемую по умолчанию при преобразовании обычных строк в строки Unicode и наоборот. Функция доступна, начиная с версии 2.0. Преобразования между типами строк Строка > юникод Код | >>> regular_string = ’обычная строка’ >>> type(regular_string) <type ’str’> >>> unicode_string = regular_string.decode(’utf-8’) >>> type(unicode_string) <type ’unicode’> |
Юникод > строка Код | >>> unicode_string = u’юникод-строка’ >>> type(unicode_string) <type ’unicode’> >>> regular_string = unicode_string.encode(’utf-8’) >>> type(regular_string) <type ’str’> |
Заключение. Как вывести список? писать собственные функции?
|