2009-05-27 3 views
7

Может кто-нибудь объяснить мне эту странную вещь:Python Юникода в Mac OS X терминала

Когда в оболочке Python Я введите следующую кириллицы строку:

>>> print 'абвгд' 
абвгд 

, но когда я типа:

>>> print u'абвгд' 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-9: ordinal not in range(128) 

Поскольку первая тройка вышла правильно, я считаю, что мой терминал OS X может представлять собой unicode, но, оказывается, он не может быть во втором случае. Зачем ?

ответ

16
>>> print 'абвгд' 
абвгд 

При вводе некоторых символов ваш терминал решает, как эти символы представлены в приложении. Ваш терминал может предоставить символы приложениям, закодированным как utf-8, ISO-8859-5, или даже то, что понимает только ваш терминал. Python получает эти символы как некоторую последовательность байтов. Затем python выводит эти байты так, как они есть, и ваш терминал каким-то образом интерпретирует их для отображения символов. Так как ваш терминал обычно интерпретирует байты таким же образом, как он закодирован их прежде, все отображается, как вы ввели его.

>>> u'абвгд' 

Здесь вы вводите в некоторых символов, которые поступают на питона переводчика в виде последовательности байтов, возможно, каким-то образом закодирован терминалом. С префиксом u python пытается преобразовать эти данные в unicode. Для этого python должен знать, какую кодировку использует ваш терминал. В вашем случае похоже, что Python догадывается, что кодирование ваших терминалов будет ASCII, но полученные данные не соответствуют этому, поэтому вы получаете ошибку кодирования.

Прямой вперед способ создания Юникода строки в интерактивной сессии поэтому было бы что-то подобное это:

>>> us = 'абвгд'.decode('my-terminal-encoding') 

В файлах вы можете также указать кодировку файла с помощью специального режима линии:

# -*- encoding: ISO-8859-5 -*- 
us = u'абвгд' 

Для других способов установки кодировки ввода по умолчанию вы можете посмотреть sys.setdefaultencoding(...) или sys.stdin.encoding.

+0

Да, это имеет для меня большой смысл, спасибо. – disc0dancer

+0

+1 очень полный ответ –

0

Юникодный объект должен быть закодирован, прежде чем он будет отображаться на некоторых консолях. Попробуйте

u'абвгд'.encode() 

вместо того, чтобы кодировать юникод на объект строки (скорее всего, используя utf8 в качестве кодировки по умолчанию, но зависит от питона конфигурации)

+0

это не работает - закодировать() бросает ту же ошибку. – disc0dancer

3

Кроме того, убедитесь, что терминал кодирование установлено в Unicode/UTF-8 (а не ASCII, который, кажется, ваша установка):

http://www.rift.dk/news.php?item.7.6

+0

Я понял, что один, но то, что меня беспокоит, это то, что мой терминал DOIS отображает юникод правильно, если он напечатан как обычная строка - например. 'уникоде', но выдает ошибку, если я пытаюсь напечатать ту же строку, что и u'уникоде ' – disc0dancer

9

в дополнение к обеспечению вашего X терминала OS устанавливается в UTF-8, вы можете установить питона кодировку SYS по умолчанию к UTF-8 или лучше. Создайте файл в /Library/Python/2.5/site-packages под названием sitecustomize.py. В этом файле поместить:

import sys 
sys.setdefaultencoding('utf-8') 

Метод setdefaultencoding доступен только модулем сайта, и удаляется из sys namespace once startup has completed. Таким образом, вам нужно будет запустить новый интерпретатор python, чтобы изменения вступили в силу. Вы можете проверить текущий код по умолчанию в любое время после запуска с sys.getdefaultencoding().

Если символы уже не юникода и вам нужно преобразовать их, используйте метод decode на шнурке, чтобы декодировать текст из какой-либо другой кодировки в юникод ... лучше всего указать, какая кодировка:

s = 'абвгд'.decode('some_cyrillic_charset') # makes the string unicode 
print s.encode('utf-8') # transform the unicode into utf-8, then print it 
+0

. Это решило мои проблемы, хотя объяснение repr() неверно. Я допустил ошибку в моем вопросе (извините), который я сейчас исправил, - на самом деле я напечатал строку u'абвгд, поэтому это не ошибка repr(). Фактически - я не получаю ошибку, если опускаю оператор печати - я просто получаю u '\ xd0 \ xb0 \ xd0 \ xb1 \ xd0 \ xb2 \ xd0 \ xb3 \ xd0 \ xb4' Мое предположение было бы что кодировка по умолчанию - mac-roman каким-то образом способна представлять кириллические символы (что, с другой стороны, не имеет смысла ...), но не является кириллицей в юникоде. Я действительно не получаю это :) – disc0dancer

+0

Спасибо за информацию дискотека ... ты прав ... мой плохой. –

+0

Не меняйте системную кодировку по умолчанию; исправьте значения Unicode. Изменение кодировки по умолчанию может разорвать библиотеки, которые полагаются на, как вы знаете, * поведение по умолчанию *. Существует причина, по которой вам нужно принудительно перезагрузить модуль, прежде чем вы сможете это сделать. –

0

«абвгд» не является юникода строкой

u'абвгда»является юникода строкой

Вы не можете печатать Юникод строки без кодирующих их. Когда вы имеете дело со строками в своем приложении, вы хотите удостовериться, что любой вход декодирован и любой вывод в кодировке. Таким образом, ваше приложение будет обрабатывать только строки unicode внутри и выводить строки в UTF8.

Для справки:

>>> 'абвгд'.decode('utf8') == u'абвгд' 
>>> True 
13

На Python 2.6, вы можете использовать переменные окружения PYTHONIOENCODING сказать Python, что ваш терминал UTF-8 способен. Самый простой способ сделать это перманент, добавив следующую строку в ~/.bash_profile:

export PYTHONIOENCODING=utf-8 

Terminal.app showing unicode output from Python

+0

Спасибо, сделал мой день! – bouke

+0

Приятный пример, особенно учитывая, что сборка python OSX поставляется со скудным 'sys.maxunicode == 0xffff' –

+0

У меня была проблема с симпатичной печалью, и ваш трюк решил проблему. Спасибо. – Pouya

Смежные вопросы