Rip*_*Doc 16 python filesystems unicode macos file-io
在OS X和Python中对Unicode文件名进行了一些努力.我试图在代码中稍后使用文件名作为正则表达式的输入,但文件名中使用的编码似乎与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
Run Code Online (Sandbox Code Playgroud)
它输出以下内容:
utf-8
s [229, 228, 246] åäö
s2 [195, 165, 195, 164, 195, 182] åäö
dir [97, 778, 97, 776, 111, 776] åäö
Run Code Online (Sandbox Code Playgroud)
因此,文件系统编码是utf-8,但是当我使用它编码我的文件名时,它与我创建具有相同字符串的目录名称不同.我希望当我使用我的字符串åäö创建一个目录,然后读回它的名字时,它应该使用相同的代码,就像我直接应用编码一样.
如果我们查看代码点97,778,97,776,111,776,它基本上是加上变音符号的ASCII字符,例如o +¨=ö,这使得它成为两个字符,而不是一个字符.如何避免这种差异,Python中是否存在一种与OS X匹配此行为的编码方案,为什么getfilesystemencoding()不能给我正确的结果?
还是我搞砸了?
小智 24
MacOS X使用一种特殊的分解UTF-8来存储文件名.如果您需要读取文件名并将其写入"普通"UTF-8文件,则必须将它们标准化:
filename = unicodedata.normalize('NFC', unicode(filename, 'utf-8')).encode('utf-8')
Run Code Online (Sandbox Code Playgroud)
从这里:https://web.archive.org/web/20120423075412/http : //boodebr.org/main/python/all-about-python-and-unicode
一二三*_*一二三 19
getfilesystemencoding()正在给你正确的响应(编码),但它没有告诉你unicode规范化形式.
特别是,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')
Run Code Online (Sandbox Code Playgroud)