Вы могли обратить внимание на это или нет, но во всех предыдущих примерах текстовое содержимое было представлено в виде строк str — либо жестко определенных в тексте сценариев, либо извлекаемых из простых текстовых файлов и сохраняемых в них, что предполагает использование кодировки по умолчанию для текущей платформы. Однако технически виджет Text позволяет вставлять строки обоих типов, и str и bytes:
> >> from tkinter import Text
> >> T = Text()
> >> T.insert(‘1.0’, ‘spam’) # вставить строку типа str
> >> T.insert(‘end’, b’eggs’) # вставить строку типа bytes
> >> T.pack() # теперь виджет отображает строку “spameggs”
> >> T.get(‘1.0’, ‘end’) # извлечь содержимое
‘spameggs\n’
Возможность вставки текста в виде строки типа bytes может пригодиться при просмотре различных видов текста Юникода, особенно когда имя кодировки не известно. Например, текст, полученный из Интернета (скажем, во вложении к электронному письму или полученный по FTP), может быть представлен в любой кодировке — сохранение его в файлах в двоичном режиме и отображение, как строк типа bytes в виджете Text, может показаться обходным решением проблемы использования кодировок в наших сценариях.
Однако, к большому сожалению, виджет Text возвращает свое содержимое только в виде строки str независимо от того, строки какого типа в него вставлялись, str или bytes, — в любом случае мы получаем обратно уже декодированный текст Юникода:
> >> T = Text()
> >> T.insert(‘1.0’, ‘Textfileline1\n’)
> >> T.insert(‘end’, ‘Textfileline2\n’) # при вставке str, содержимое — str
> >> T.get(‘1.0’, ‘end’) # вызывать pack() не обязательно,
‘Textfileline1\nTextfileline2\n\n’ # чтобы обратиться к get()
> >> T = Text()
> >> T.insert(‘1.0’, b’Bytesfileline1\r\n’) # для bytes содержимое тоже str!
> >> T.insert(‘end’, b’Bytesfileline2\r\n’) # а \r отображается, как пробел
> >> T.get(‘1.0’, ‘end’)
‘Bytesfileline1\r\nBytesfileline2\r\n\n’
Фактически мы получаем содержимое виджета в виде строки типа str, даже если мы вставляли строки обоих типов, str и bytes, с единственным символом \n, добавленным в конец, как показано в первом примере в этом разделе. Ниже приводится более полная иллюстрация:
> >> T = Text()
> >> T.insert(‘1.0’, ‘Textfileline1\n’)
> >> T.insert(‘end’, ‘Textfileline2\n’) # добавлены две строки str
> >> T.insert(‘1.0’, b’Bytesfileline1\r\n’) # \n добавляется для любого типа
> >> T.insert(‘end’, b’Bytesfileline2\r\n’) # pack() отображает 4 строки текста
> >> T.get(‘1.0’, ‘end’)
‘Bytesfileline1\r\nTextfileline1\nTextfileline2\nBytesfileline2\r\n\n’
>>>
> >> print(T.get(‘1.0’, ‘end’))
Bytesfileline1
Textfileline1
Textfileline2
Bytesfileline2
Это упрощает обработку текста содержимого после его извлечения: мы можем интерпретировать его, как строку типа str независимо от того, строки каких типов вставлялись. Однако эта же особенность усложняет обработку текстовых данных с точки зрения Юникода: мы не можем сохранить возвращаемую строку str в двоичный файл, потому что операция записи в двоичном режиме ожидает получить строку типа bytes. Нам необходимо будет либо закодировать строку в тип bytes вручную, либо открыть файл в текстовом режиме и уповать на то, что строка str сможет быть закодирована. В любом случае нам необходимо будет знать имя применяемой кодировки; положиться на кодировку по умолчанию для данной платформы; в крайнем случае, сделать какие-либо предположения и надеяться, что они оправдаются; или запросить кодировку у пользователя.
Иными словами, даже при том, что библиотека tkinter позволяет вставлять текст в неизвестной кодировке, как строку типа bytes, и просматривать его, тот факт, что содержимое возвращается в виде строки str, в общем случае означает необходимость знать, как кодировать текст при сохранении, чтобы удовлетворить интерфейс файлов в Python 3.X. Кроме того, так как строки bytes, вставляемые в виджеты Text, также должны быть декодируемыми согласно ограничениям поддержки Юникода в библиотеке Tk, будет лучше, если мы будем декодировать текст в строки str самостоятельно, чтобы обеспечить более широкую поддержку Юникода. Чтобы убедиться в правоте этих слов, нам необходимо совершить короткий экскурс в страну Юникода.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011