Unicode-кодировка для файловой системы в Mac OS X неверна в Python? - PullRequest
15 голосов
/ 18 марта 2012

Немного борьбы с именами файлов 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 с той же строкой. Я ожидаю, что когда я использую мою строку åäö для создания dir и читаю его имя обратно, он должен использовать те же коды, как если бы я применил кодировку напрямую.

Если мы посмотрим на кодовые точки 97, 778, 97, 776, 111, 776, то это в основном символы ASCII с добавлением диакритического знака, например, o + ¨ = ö, что делает его двумя символами, а не одним. Как я могу избежать этого несоответствия, есть ли в Python схема кодирования, которая соответствует этому поведению в OS X, и почему getfilesystemencoding () не дает мне правильный результат?

Или я все испортил?

Ответы [ 2 ]

24 голосов
/ 18 марта 2012

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

18 голосов
/ 18 марта 2012

getfilesystemencoding() дает вам правильный ответ ( кодировка ), но он не сообщает вам форму нормализации Юникода .

В частности,Файловая система HFS + использует кодировку UTF-8 и форму нормализации, близкую к «D» (которая требует, чтобы составные символы, такие как ö, были разложены на ).HFS + также привязан к форме нормализации, как это было в Unicode версии 3.2 - как подробно описано в документации Apple для формата HFS + .

Преобразование метода unicodedata.normalize в Pythonмежду формами, и если вы префикса вызова с объектом ucd_3_2_0, вы можете ограничить его Unicode версии 3.2:

filename = unicodedata.ucd_3_2_0.normalize('NFC', unicode(filename, 'utf-8')).encode('utf-8')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...