Кодировка Unicode для файловой системы в Mac OS X неверна в Python?
Имея немного борьбы с именами файлов Unicode в OS X и Python. Я пытаюсь использовать имена файлов в качестве ввода для регулярного выражения позже в коде, но кодировка, используемая в именах файлов, кажется, отличается от того, что говорит мне sys.getfilesystemencoding(). Возьмите следующий код:
#!/usr/bin/env python
# coding=utf-8
import sys,os
print sys.getfilesystemencoding()
p = u'/temp/s/'
s = u'åäö'
print 's', [ord(c) for c in s], s
s2 = s.encode(sys.getfilesystemencoding())
print 's2', [ord(c) for c in s2], s2
os.mkdir(p+s)
for d in os.listdir(p):
print 'dir', [ord(c) for c in d], d
Выводит следующее:
utf-8
s [229, 228, 246] åäö
s2 [195, 165, 195, 164, 195, 182] åäö
dir [97, 778, 97, 776, 111, 776] åäö
Итак, кодировка файловой системы - utf-8, но когда я кодирую свое имя файла åäö, используя это, это будет не так, как если бы я создал имя dir с той же строкой. Я ожидаю, что, когда я использую свою строку åäö для создания каталога и прочитаю его имя назад, он должен использовать те же коды, как если бы я применил кодировку напрямую.
Если мы посмотрим на кодовые точки 97, 778, 97, 776, 111, 776, это в основном символы ASCII с добавлением диакритических знаков, например. o + ¨ = ö, что делает его двумя символами, а не одним. Как я могу избежать этого несоответствия, существует ли схема кодирования в Python, которая соответствует этому поведению OS X, и почему не получается getfilesystemencoding(), давая мне правильный результат?
Или я испортился?
Ответы
Ответ 1
MacOS X использует специальный тип разложенного UTF-8 для хранения имен файлов. Если вам нужно, например, читать в именах файлов и записывать их в "обычный" файл UTF-8, вы должны их нормализовать:
filename = unicodedata.normalize('NFC', unicode(filename, 'utf-8')).encode('utf-8')
отсюда: https://web.archive.org/web/20120423075412/http://boodebr.org/main/python/all-about-python-and-unicode
Ответ 2
getfilesystemencoding()
дает вам правильный ответ (кодирование), но он не сообщает вам форму unicode normalization.
В частности, файловая система HFS + использует кодировку UTF-8 и форму нормализации, близкую к "D" (для которой требуется скомпоновать символы типа ö
в o¨
). HFS + также привязан к форме нормализации, как он существовал в Unicode версии 3.2, как описано в документации Apple для формата HFS +.
Python unicodedata.normalize
метод конвертирует между формами, а если вы префикс вызова с объектом ucd_3_2_0
, вы можете ограничить его в Unicode версии 3.2:
filename = unicodedata.ucd_3_2_0.normalize('NFC', unicode(filename, 'utf-8')).encode('utf-8')