Python unicode в терминале 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, но, оказывается, он не может во втором случае. Почему ?
6 ответов
>>> print 'абвгд'
абвгд
при вводе некоторые символы, ваш терминал решает, как эти символы представлены в приложении. Ваш терминал может дать символы приложению, закодированные как utf-8, ISO-8859-5 или даже что-то, что понимает только ваш терминал. Python получает эти символы в виде некоторой последовательности байтов. Затем python печатает эти байты так, как они есть, и ваш терминал интерпретирует их каким-то образом для отображения символов. Поскольку ваш терминал обычно интерпретирует байты так же, как он кодировал их раньше, все отображается так, как вы его ввели.
>>> u'абвгд'
здесь вы вводите некоторые символы, которые поступают в интерпретатор python в виде последовательности байтов, возможно, закодированных каким-то образом терминалом. С u
префикс python пытается преобразовать эти данные в unicode. Чтобы сделать это правильно, python должен знать, какую кодировку использует ваш терминал. В вашем случае похоже, что Python догадывается, что ваша кодировка терминалов будет ASCII, но полученная данные не соответствуют этому, поэтому вы получаете ошибку кодирования.
прямой способ создания строк unicode в интерактивном сеансе был бы таким:
>>> us = 'абвгд'.decode('my-terminal-encoding')
в файлы, вы также можете указать кодировку файла с помощью специальной строки:
# -*- encoding: ISO-8859-5 -*-
us = u'абвгд'
для других способов установить кодировку ввода по умолчанию вы можете посмотреть на sys.setdefaultencoding(...)
или sys.stdin.encoding
.
начиная с Python 2.6, вы можете использовать переменную окружения PYTHONIOENCODING
чтобы сообщить Python, что ваш терминал поддерживает UTF-8. Самый простой способ сделать это постоянным-добавить следующую строку в ваш ~/.bash_profile
:
export PYTHONIOENCODING=utf-8
в дополнение к обеспечению того, что ваш терминал OS X установлен в UTF-8, вы можете установить кодировку python sys по умолчанию в UTF-8 или лучше. Создайте файл в /Library/Python/2.5/site-packages
под названием sitecustomize.py
. В этом файле ставим:
import sys
sys.setdefaultencoding('utf-8')
на setdefaultencoding
метод доступен только модулем сайта и удаляется из пространство имен sys после завершения запуска. Таким образом, вам нужно будет запустить новый интерпретатор python, чтобы изменения вступили в силу. Можно проверить текущее значение по умолчанию кодирование в любое время после запуска с помощью sys.getdefaultencoding()
.
если символы еще не unicode, и вам нужно преобразовать их, используйте decode
метод в строке для декодирования текста из какой-либо другой кодировки в unicode... лучше всего указать, какая кодировка:
s = 'абвгд'.decode('some_cyrillic_charset') # makes the string unicode
print s.encode('utf-8') # transform the unicode into utf-8, then print it
кроме того, убедитесь, что кодировка терминала установлена в Unicode / UTF-8 (а не ascii, который, похоже, является вашей настройкой):
объект unicode должен быть закодирован, прежде чем его можно будет отобразить на некоторых консолях. Попробуй!--2-->
u'абвгд'.encode()
вместо того, чтобы кодировать Юникод в строковый объект (скорее всего, используя utf8 в качестве кодировки по умолчанию, но зависит от вашей конфигурации python)
'абвгд' не является строкой юникода
u'абвгд' - строка Юникода
вы не можете печатать строки unicode без их кодирования. Когда вы имеете дело со строками в своем приложении, вы хотите убедиться, что любой вход декодирован и любой выход закодирован. Таким образом, ваше приложение будет иметь дело только со строками unicode внутри и выводить строки в UTF8.
Для справки:
>>> 'абвгд'.decode('utf8') == u'абвгд'
>>> True