Правила, описанные в предыдущем разделе, могут показаться слишком сложными, но в действительности все они сводятся к следующему:
• Кодировку, используемую в операциях чтения/записи в текстовом режиме и при кодировании/декодировании вручную, необходимо знать только при работе со строками, кодировка символов в которых не совпадает с кодировкой, используемой на текущей платформе по умолчанию.
• Для записи в новые файлы можно использовать практически любую кодировку, при условии, что она может применяться к символам в строках, но при чтении необходимо указывать кодировку, совместимую с имеющимися двоичными данными.
• При чтении текста в двоичном режиме для отображения в виджете знать кодировку необязательно, но виджет Text всегда возвращает содержимое в виде строки str, поэтому, чтобы закодировать его перед сохранением в файл, необходимо знать кодировку.
Так почему бы всегда не загружать текст для отображения в виджете Text в двоичном режиме? Хотя чтение из файлов в двоичном режиме и кажется решением проблем кодирования, тем не менее передача текста библиотеке tkinter в виде строк bytes вместо str в действительности просто перекладывает проблему кодирования на библиотеку Tk, которая налагает собственные ограничения.
В частности, может показаться, что открывая входные файлы в двоичном режиме, мы обеспечиваем возможность отображения произвольных текстовых данных, но у этого решения есть два недостатка:
• Оно снимает бремя выбора кодировки с нашего сценария и перекладывает его на библиотеку Tk. Библиотеке все равно придется решать,
как отображать полученные байты, и может так случиться, что она не будет поддерживать какие-то необходимые кодировки.
• Оно позволяет открывать и просматривать файлы, которые по своей природе не являются текстовыми, сводя к нулю некоторые из преимуществ, предлагаемых проверками, выполняемыми при декодировании текста.
Первый пункт является, пожалуй, наиболее важным. Поэкспериментировав в Windows, я выяснил, что библиотека Tk корректно обрабатывает строки bytes в кодировках ASCII, UTF-8 и Latin-1, но не справилась с кодировкой UTF-16 и другими, такими как CP500. Однако все эти строки отображаются корректно, когда перед передачей библиотеке Tk двоичные данные декодируются в строку str. В программах, предназначенных для использования по всему миру, такая расширенная поддержка становится жизненно значимой. Если у вас есть возможность определить кодировку или запросить ее у пользователя, то для отображения и сохранения текста в файлы лучше использовать строки str.
Независимо от того, передаете вы текстовые данные в виде строк типа str или bytes, графические интерфейсы на основе библиотеки tkinter подчиняются ограничениям, накладываемым библиотекой Tk и языком программирования Tcl, а также всеми приемами использования библиотеки tkinter в языке Python, которая служит интерфейсом к библиотеке Tk. Например:
• Tcl, внутренний язык реализации библиотеки Tk, хранит строки в кодировке UTF-8 и требует, чтобы строки передавались через его прикладной интерфейс на языке C именно в этом формате.
• Tcl пытается преобразовать строки байтов, используя кодировку UTF-8, и в целом поддерживает преобразования с использованием кодировок, определяемых региональными настройками системы и кодировки Latin-1, как последнего средства.
• Реализация библиотеки tkinter на языке Python передает строки bytes языку Tcl без промежуточных преобразований, но при использовании строк Юникода типа str копируются объекты Юникода языка Tcl.
• Библиотека Tk унаследовала все ограничения языка Tcl, связанные с Юникодом, и добавляет свои ограничения, связанные с выбором шрифта для отображения.
Иными словами, графические интерфейсы, отображающие текст с использованием средств библиотеки tkinter, находятся во власти нескольких слоев программного обеспечения, расположенных выше и ниже программного кода на языке Python. Но, как бы то ни было, Юникод достаточно полно поддерживается виджетом Text из библиотеки Tk при использовании строк типа str, хотя это не относится к строкам bytes. Как вы уже наверняка заметили, обсуждение этой проблемы быстро начинает обрастать техническими деталями, поэтому мы не будем исследовать ее дальше в этой книге — дополнительные сведения о tkinter, Tk и Tcl и интерфейсах между ними ищите в Сети или в других источниках информации.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011