在使用Python 2.7时,为什么我的Unicode文件名在调用file()时会引发IOError?

1 投票
2 回答
4037 浏览
提问于 2025-04-16 09:51
sys.getdefaultencoding()

Python 2.7:

我正在尝试打开一个mp3文件,以读取它的ID3标签,使用的是mutagen库(所以我不想更改方法),调用的是:

file(filename, "rb")

对于没有特殊字符的文件,这样做没问题,但有时候我似乎会遇到

IOError: [Errno 2] No such file or directory: u"somepath\\08 - Muse - I Belong To You - Mon C\x9cur S'ouvre \xc0 Ta Voix.mp3"

而其他时候

u"somepath\\02 - Max\xefmo Park - Apply Some Pressure.mp3"

则正常工作。

这两者之间有什么区别?为什么一个能工作而另一个不行呢?

谢谢,

Felix

编辑:在Eclipse的pydev下运行时,它工作正常,返回的是"Cp1252",但从命令行运行时返回的是"ascii"。当文件名打印到Eclipse控制台时是

u"somepath\\08 - Muse - I Belong To You - Mon C\u0153ur S'ouvre \xc0 Ta Voix.mp3"

编辑:从Winamp(音乐播放器)获取文件名的代码是:

winampProcess = win32api.OpenProcess(win32con.PROCESS_VM_READ, False, processID)
memoryBuffer = ctypes.create_string_buffer(256)
ctypes.windll.kernel32.ReadProcessMemory(winampProcess.handle, memoryPointer, memoryBuffer, 256, 0)
winampProcess.Close()
rawPath = win32api.GetFullPathName(memoryBuffer.raw.split("\x00")[0])
try:
    unicodeString = unicode(rawPath)
except UnicodeDecodeError:
    unicodeString = u""
    for char in rawPath:
        try:
            unicodeString += unicode(char)
        except UnicodeDecodeError as err:
            errStr = str(err)
            startIndex = errStr.index("0x")
            endIndex = errStr.index(" ", startIndex)
            hexStr = ""
            for i in range(startIndex, endIndex):
                hexStr += errStr[i]
            unicodeString += unichr(int(hexStr, 16))
return unicodeString

编辑:如果我明确设置

unicode(str, "cp1252")

问题就解决了,但我仍然不明白是什么导致了这个问题,这只是一个临时的解决办法,可能对其他有问题的文件名不管用……

2 个回答

1

使用 os.listdir() 函数查看目录里的文件名,看看它是怎么编码的。然后把这个文件名和你用 filename.encode('cp1252') 得到的结果进行对比。你应该能发现两者之间的不同,这样就能知道问题出在哪里了。

我能想到的唯一真正的问题是,有些东西被解码了两次。你也可能会遇到规范化的问题,但在这种情况下,这种可能性似乎不大。

1

我猜测,你是从一个程序中获取文件名,而这个程序使用的是当前默认编码下的多字节字符集。在英文版的Windows中,默认编码是cp1252。Ascii编码不包含任何扩展字符,这就是为什么当你尝试用Ascii编码把字符串转换成Unicode时会出现错误。

补充一下:这个回答提供了一些关于在当前Windows代码页中编码文件名的信息。

撰写回答