Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> проблема python 2.6 с кодировками !наболело! я рассматриваю различные способы решения 
:(
    Опции темы
beliyshum
  Дата 11.4.2009, 19:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 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’>



Заключение. Как вывести список? писать собственные функции? 
PM MAIL   Вверх
Daevaorn
Дата 11.4.2009, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: 9
Всего: 70



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

list/dict в __str__/__unicode__ методах вызывают repr для своих элементов. Отсюда и все особенности вывода.
PM MAIL WWW   Вверх
beliyshum
Дата 11.4.2009, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 21.3.2009

Репутация: нет
Всего: нет



Daevaorn, я новичок, и не очень понял что вы хотели сказать, не могли бы вы пояснить на примерах?
PM MAIL   Вверх
beliyshum
Дата 12.4.2009, 09:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 21.3.2009

Репутация: нет
Всего: нет



Daevaorn, я хотел этим постом показать все способы, которыми пытался решить проблему, и хотел бы узнать от профессионалов, как же на самом деле это надо делать, и что я делал не правильно.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Python: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1140 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.