Все вышеизложенное имеет прямое отношение к виджету Text: если файл открывается в двоичном режиме, отпадает необходимость беспокоиться о кодировках — библиотека tkinter будет интерпретировать данные в соответствии с нашими ожиданиями, по крайней мере, для этих двух кодировок:
> >> from tkinter import Text
> >> t = Text()
> >> t.insert(‘1.0’, open(‘ldata’, ‘rb’).read())
> >> t.pack() # строка появится в графическом интерфейсе
> >> t.get(‘1.0’, ‘end’)
‘AABaC\n’
>>>
> >> t = Text()
> >> t.insert(‘1.0’, open(‘udata’, ‘rb’).read())
> >> t.pack() # строка появится в графическом интерфейсе
> >> t.get(‘1.0’, ‘end’)
‘AABaC\n’
Виджет действует, как если бы мы передали ему строку str, извлеченную в текстовом режиме, но при использовании текстового режима нам необходимо передать интерпретатору Python имя кодировки — операции чтения будут терпеть неудачу при использовании кодировки, несовместимой с данными, хранящимися в файле:
> >> t = Text()
> >> t.insert(‘1.0’, open(‘ldata’, ‘r’, encoding=’latin-1’).read())
> >> t.pack()
> >> t.get(‘1.0’, ‘end’)
‘AABaC\n’
>>>
> >> t = Text()
> >> t.insert(‘1.0’, open(‘udata’, ‘r’, encoding=’utf-8’).read())
> >> t.pack()
> >> t.get(‘1.0’, ‘end’)
‘AABaC\n’
В любом случае содержимое, извлеченное из файла, всегда будет представлено строкой Юникода str, поэтому двоичный режим оказывает влияние только на операцию чтения. Но нам тем не менее необходимо знать кодировку, сохраняем мы данные непосредственно в текстовом режиме или выполняем запись в двоичном режиме после кодирования вручную:
> >> c = t.get(‘1.0’, ‘end’)
> >> c # содержимое — строка str
‘AABaC\n’
> >> open(‘cdata’, ‘wb’).write(c) # binary mode needs bytes
TypeError: must be bytes or buffer, not str
> >> open(‘cdata’, ‘w’, encoding=’latin-1’).write(c) # каждая операция записи
> >> open(‘cdata’, ‘rb’).read() # возвращает число 6
b’A\xc4B\xe4C\r\n’
> >> open(‘cdata’, ‘w’, encoding=’utf-8’).write(c) # другие байты в файле
> >> open(‘cdata’, ‘rb’).read()
b’A\xc3\x84B\xc3\xa4C\r\n’
> >> open(‘cdata’, ‘w’, encoding=’utf-16’).write(c)
> >> open(‘cdata’, ‘rb’).read()
b’\xff\xfeA\x00\xc4\x00B\x00\xe4\x00C\x00\r\x00\n\x00’
> >> open(‘cdata’, ‘wb’).write( c.encode(‘latin-1’) ) # закодировать вручную
> >> open(‘cdata’, ‘rb’).read() # то же, но с \r в Win
b’A\xc4B\xe4C\n’
> >> open(‘cdata’, ‘w’, encoding=’ascii’).write(c) # должна быть совместимой UnicodeEncodeError: ‘ascii’ codec can’t encode character ‘\xc4’ in position 1: o
Обратите внимание на последнюю операцию в этом примере: операция кодирования вручную и записи в файл может терпеть неудачу, если данные не смогут быть закодированы с применением указанной кодировки. Когда такое случается, программа, вероятно, должна восстановиться после исключения и попробовать альтернативную кодировку — это особенно справедливо для платформ, где в качестве кодировки по умолчанию используется ASCII.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011