Форум сайта python.su
SciTE, WinXP.
# -*- coding: utf-8 -*- print u'Привет, Мир!'
# -*- coding: cp1251 -*- print unicode('Привет, Мир!', 'cp1251')
UnicodeEncodeError: ‘ascii’ codec can't encode characters in position 0-5: ordinal not in range(128)Вне SciTE всё работает правильно. Как побороть SciTE?
Офлайн
как обычно вопрос не в SciTe или XXX (подставить любой редактор или инструмент), а в том, что 99,99999% питон-программистов не понимают, что печатать unicode строки в общем случае НЕЛЬЗЯ!!! Возьмите ручку и напишите 1000 раз на листике бумаги: Я НИКОГДА НЕ БУДУ ПЕЧАТАТЬ UNICODE-СТРОКИ
Когда вы работаете интерактивно, то ваш sys.stdout подключен к реальному терминальному окну. К РЕАЛЬНОМУ. Которе имеет конечно какую-то дефолтную кодировку выводимых символов. Питон при старте интерпретатора ловит наличие реального терминала, определяет какая кодировка там используется и создает специальную ОБВЕРТКУ вокруг потока STDOUT, которая обеспечивает перекодирование unicode-символов. Именно с этой обверткой мы имеем дело, когда говорим sys.stdout.
Когда же питон-скрипт вызывается как субпроцесс (сюрпрайз-сюрпрайз! именно так запускают скрипты почти все редакторы, чтобы перехватить вывод интерпретатор и показать его красиво в своем специальном окне), ИЛИ же вывод скрипта перенаправляется в файл или через pipe в программу типа less или more:
python script.py > file.log
python script.py | more
то у нас нет реального терминала. Есть просто поток вывода. Файловый поток. Который ничего не знает о кодировках.
В этом случае при старте питон интерпретатора для потока sys.stdout никакой перекодирующей обвертки не создается! И вот тут-то все не-ascii программисты и пользователи ловят UnicodeDecodeError. И начинается: о ужас! что же делать??? SciTe глючит! XXX глюкало! на помойку!
Товарищи! Выкиньте на помойку свои примитивные программы или по крайней мере забудьте о том, что символы с кодом больше 127 вообще существуют.
Кто виноват мы вроде разобрались.
Теперь: что делать.
А делать надо вот что.
Самый правильный и занудный вариант: никогда не печатать юникодные строки, а перекодировать их ручками в нужную кодировку: print unistr.encode('cp1251')
Только руки устанут кодировать такое.
Другой правильный путь (он более сложный, но не занудный):
1) проверить что sys.stdout подключен к реальному терминалу: sys.stdout.isatty()
2) если не подключен, что делаем обвертку руками:
import codecs
outf = codecs.getwriter('cp1251')(sys.stdout)
Офлайн
bialix
Спасибо большое, отличная статья!
Но. Чтобы эта статья была действительно полезна для тех, кому она и предназначена (т.е. для новичков), нужно решить несколько моментов.
1.
bialixЗдесь обязательно нужен пример кода.
…и использовать поток outf для вывода ваших замечательных юникодных строк.
bialixЗдесь обязательно нужен пример кода.
Можно даже подменить sys.stdout этой обверткой.
bialixОгромная, дикая просьба от лица всего начинающего-русскоязычного-питонопишушего человечества преодолеть лень :).
Для того, чтобы определить кодировку терминала надо немного больше усилий. Мне щас лень копи-пастить код…
Офлайн
The gray CardinalС вашими замечаниями согласен, ибо тема эта действительно наболела.
bialix
Спасибо большое, отличная статья!
Но. Чтобы эта статья была действительно полезна для тех, кому она и предназначена (т.е. для новичков), нужно решить несколько моментов.
Офлайн
Не совсем верно.
На самом деле бывают и юникодные терминалы %).
Например - попробуйте в IDLE сделать вывод.
Как вывод:
Надо просто осознавать - какой у вас терминал.
Отредактировано (Ноя. 14, 2007 19:56:00)
Офлайн
bialix
Самый правильный и занудный вариант: никогда не печатать юникодные строки, а перекодировать их ручками в нужную кодировку: print unistr.encode('cp1251')
# -*- coding: utf-8 -*- print u'Привет!'.encode('cp866')
bialix
использовать поток outf для вывода ваших замечательных юникодных строк
# -*- coding: utf-8 -*- import codecs, sys outf = codecs.getwriter('cp866')(sys.stdout) print >> outf, u'Привет!'
Отредактировано (Ноя. 15, 2007 13:33:28)
Офлайн
Не знаю как у вас (Все ники заняты), но у меня SciTe настроен на юникод: в глобальных опциях стоит “code.page=65001” и “output.code.page=65001” (все исходные файлы в utf-8).
Вот этот вариант работает у меня в SciTe:
import codecs, sys
outf = codecs.getwriter('utf-8')(sys.stdout)
print >> outf, u'Привет!'
И опять же, какой редактор (терминал) - так он и покажет. Надо определиться и выбрать что-то одно, я вообще не вижу для себя смысла выводить юникодные строки, есть (будет) лог программы, который и будет понимать меня так, как я хочу - тогда я вообще избавлюсь от всех print-ов, тем более что в python3000 их всё равно надо будет переделывать, хоть и будут (есть) средства автоматизации этого процесса.
Офлайн
Сейчас поставил в SciTE:
code.page=65001Код:
output.code.page=65001
# -*- coding: utf-8 -*- import codecs, sys outf = codecs.getwriter('utf-8')(sys.stdout) print >> outf, u'Привет!'
>pythonw -u “test.py”
ǟT&̦-ƦT¡
>Exit code: 0 Time: 0.212
Офлайн
Еще есть такая штука как
import sys
sys.stdout.encoding
Возвращает кодировку терминала. Но не во всех редакторах ее можно получить.
Отредактировано (Ноя. 15, 2007 16:43:33)
Офлайн
shizaВ консоли у меня это - cp866.
Еще есть такая штука как
import sys
sys.stdout.encoding
Возвращает кодировку терминала. Но не во всех редакторах ее можно получить.
Офлайн