Найти - Пользователи
Полная версия: Несколько вопросов по работе с utf-8.
Начало » Python для новичков » Несколько вопросов по работе с utf-8.
1
corpse
Добрый всем день. Я только начал изучать питон, но сразу столкнулся с проблемой кодировок. Бьюсь третий день, искал на форумах и далеко не только на этом, но нигде не нашёл внятных исчерпывающих ответов на свои вопросы. Надеюсь найти тут.

Debian lenny 5.0.3, соответственно родная кодировка - utf-8, python 2.5.2.
Считываю из файла в кодировке utf-8 строку, например, в переменную test:
>>> print test
Как дела?
Строка при выводе отображается совершенно нормально. Не смотря на то, что в питоне по умолчанию ASCCI.
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
Вопрос номер раз: в текущий момент кодировка питона ascii, кодировка считанной строки - utf-8, строка отображается нормально. В какой кодировке она сейчас? Мне хочется это понимать.
А теперь мы производим какое-либо действие над строкой. Например, split:
>>> print test.split()
['\xd0\x9a\xd0\xb0\xd0\xba', '\xd0\xb4\xd0\xb5\xd0\xbb\xd0\xb0?']
Сюрприз! Получили каку, которая упоминается на каждом втором форуме по питону при разборе проблем с кодировками. А теперь попробуем вывести каждый элемент отдельно:
>>> print test.split()[0], test.split()[1]
Как дела?
Вопрос номер два: почему в предыдущем примере всё отображается в неверной кодировке, хотя сами строки в utf-8 выводятся замечательно?

А теперь сменим кодировку по умолчанию для питона так, как это показано тут: http://doweb.sloyko.com/index.php?/archives/22-Strah_i_nenavist_setdefaultencoding.html и убедимся, что в поведении питона ровным счётом ничего не изменилось.
Ссылку привёл на случай, если кто-то спросит, зачем перезагружать модуль sys.
>>> import sys
>>> reload(sys)
<module 'sys' (built-in)>
>>> sys.setdefaultencoding('utf-8')
>>> sys.getdefaultencoding()
'utf-8'
>>> print test
Как дела?
>>> print test.split()
['\xd0\x9a\xd0\xb0\xd0\xba', '\xd0\xb4\xd0\xb5\xd0\xbb\xd0\xb0?']
>>> print test.split()[0]
Как
>>> print test.split()[0], test.split()[1]
Как дела?
Вопрос номер три: какой тогда вообще смысл в кодировке по умолчанию в питоне, если от её смены совершенно не изменяется реакция на обработку строк в данном примере?

Надо сказать, что введённые с экрана строки обладают всё теми же замечательными свойствами.
>>> test1 = 'Мама мыла раму'
>>> print test1
Мама мыла раму
>>> print test1.split()
['\xd0\x9c\xd0\xb0\xd0\xbc\xd0\xb0', '\xd0\xbc\xd1\x8b\xd0\xbb\xd0\xb0', '\xd1\x80\xd0\xb0\xd0\xbc\xd1\x83']
>>> [test, test1]
['\xd0\x9a\xd0\xb0\xd0\xba \xd0\xb4\xd0\xb5\xd0\xbb\xd0\xb0?', '\xd0\x9c\xd0\xb0\xd0\xbc\xd0\xb0 \xd0\xbc\xd1\x8b\xd0\xbb\xd0\xb0 \xd1\x80\xd0\xb0\xd0\xbc\xd1\x83']
Вопрос номер четыре: Вообще, каким-то образом есть возможность увидеть на экране содержимое списка по-русски?

Это было бы очень удобно в процессе отладки. Перекодировать туда-сюда каждую строку тоже не дело. Писать функцию, перебирающую список и склеивающую из нужных элементов строку в случае необходимости отобразить её на экране - бред. Переходить сразу на третий (не знаю, есть ли там такие проблемы) не хочется, ибо не на каждом сервере найдётся третий. И ведь это не проблема какой-то конкретной версии. Проверил на соседней машине под убунтой (Python 2.6.4) - всё работает в точности так же. И ладно бы, дело было просто в отображении. Это серьёзно мешает жить:
>>> import sqlite3
>>> db = sqlite3.connect(':memory:')
>>> db.execute('create table list1 (field1, field2)')
<sqlite3.Cursor object at 0x7fca397bb7c0>

>>> tmp = (test.split()[0], test.split()[1])
>>> print tmp
('\xd0\x9a\xd0\xb0\xd0\xba', '\xd0\xb4\xd0\xb5\xd0\xbb\xd0\xb0?')

>>> db.execute("insert into list1 values (?, ?)", tmp )
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
sqlite3.ProgrammingError: You must not use 8-bit bytestrings unless you use a text_factory that can interpret 8-bit bytestrings (like text_factory = str). It is highly recommended that you instead just switch your application to Unicode strings.
И это при том, что у нас:
>>> sys.getdefaultencoding()
'utf-8'
Помогите пожалуйста, буду очень признателен.
Ferroman
1. Юникод.
2. В каждом втором треде про кодировки говорят, что в случае такого вывода выводится repr списка.
3. Потому что в данном примере нет никакой обработки строк. Операции, которые вы используете, не имееют отношения к дефолтной кодировке. Правда, для юникодной консоли. В каком-нибудь виндовсе в консоль выводилсь бы неверно, постольку консоль там не юникодная.
4. Выводя каждый елемент отдельно. Повторюсь, при выводе списка выводитс repr - внутреннее представление этого самого списка.
corpse
Ferroman
1. Юникод.
2. В каждом втором треде про кодировки говорят, что в случае такого вывода выводится repr списка.
Замечательно. Это я тоже понять могу.
3. Потому что в данном примере нет никакой обработки строк. Операции, которые вы используете, не имееют отношения к дефолтной кодировке. Правда, для юникодной консоли. В каком-нибудь виндовсе в консоль выводилсь бы неверно, постольку консоль там не юникодная.
4. Выводя каждый елемент отдельно. Повторюсь, при выводе списка выводитс repr - внутреннее представление этого самого списка.
Большое спасибо! Вы очень прояснили ситуацию. Во всём остальном яразобрался сам.
>>> test = u'Мама мыла раму'
>>> test1 = 'Мама мыла раму'
>>> repr(test)
"u'\\u041c\\u0430\\u043c\\u0430 \\u043c\\u044b\\u043b\\u0430 \\u0440\\u0430\\u043c\\u0443'"
>>> repr(test1)
"'\\xd0\\x9c\\xd0\\xb0\\xd0\\xbc\\xd0\\xb0 \\xd0\\xbc\\xd1\\x8b\\xd0\\xbb\\xd0\\xb0 \\xd1\\x80\\xd0\\xb0\\xd0\\xbc\\xd1\\x83'"
>>> test == test1.decode("utf-8")
True
Ferroman
+1
Dimka665
from pprint import pprint
или писать на 3-ем питоне)))
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB