Как и следовало ожидать, я столкнулся с проблемой кодировок.
в 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']
>>>
# -*- 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']]
>>>
Способ 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")
в командной сторке:
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'>
код:
# -*- 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
полезная справка:
setdefaultencoding(encoding)
Устанавливает кодировку, которая будет использоваться по умолчанию при пре образовании обычных строк в строки Unicode и наоборот. Если строка encoding не соответствует доступной кодировке, генерирует исключение LookupError. Эта функция предназначена для использования в модуле site (или sitecustomize), после этого она обычно удаляется из пространства имен модуля sys. Функция доступна, начиная с версии 2.0.
unicode(string [, encoding ])
Преобразует строку 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’>