Юникод-символы являются абстрактными объектами, называемыми кодовыми точками, и имеют несколько кодировок, таких как UTF32, UTF16 и UTF8. Для выражения всех символов в одном объекте потребуется 6 байт на символ (и даже тогда в unicode будут символы с интервалом, чтобы можно было утверждать, что размер еще больше). Чтобы все было запутанно, во многих системах использовались «кодовые страницы», существовавшие до стандартизации Unicode, которые представляют собой разные сопоставления между битами и отображаемыми ими символами.
Юникодными символами Python являются UTF16 в ОЗУ. Поэтому мы сразу видим проблему. Если вы хотите писать как UTF8, строка в памяти не будет работать. Python должен прочитать строку UTF16 в памяти и написать строку UTF8.
Существует еще одна тонкая проблема, которая заключается в том, что процессоры на базе процессоров Intel являются «малоконечными», но многобайтовые кодировки Unicode являются «большими эндитами» (что означает, что байты внутри слова упорядочены по-разному). Даже если вы хотите написать UTF-16, необходимо внести изменения. Из-за этой маленькой/большой проблемы обычно записывается спецификация (байтовый порядок) в начале строк, чтобы энкодеры могли угадать формат.
Персонажи могут быть выражены разными способами (кодировками), так что должно быть по умолчанию? это историческая вещь. Поскольку ACSII был таким, как это было сделано за всю историю (ну, по крайней мере, история unix), по-прежнему она по умолчанию.
При написании недвоичных данных мы всегда должны проходить через какой-то кодек. Это цена, которую мы платим за время, затрачиваемое на многоязычные вычисления, и чтобы вычислительные системы стали достаточно мощными, чтобы справиться с этим. Ни в коем случае мой Commodore 64 не имел бы дело с Phoenician.
Поскольку только кодировка определяет, какие биты (или, скорее, байты) составляют строку юникода. – sebastian