在python中使用编解码器utf-8导致文件打开错误

在python中使用编解码器utf-8导致文件打开错误,python,unicode,utf-8,Python,Unicode,Utf 8,我在WindowsXP和Python2.6.4上执行以下代码 但它显示了一个错误 如何打开名为utf-8编解码器的文件 >>> open( unicode('한글.txt', 'euc-kr').encode('utf-8') ) Traceback (most recent call last): File "<pyshell#0>", line 1, in <module> open( unicode('한글.txt', 'euc-kr

我在WindowsXP和Python2.6.4上执行以下代码

但它显示了一个错误

如何打开名为utf-8编解码器的文件

>>> open( unicode('한글.txt', 'euc-kr').encode('utf-8') )

Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    open( unicode('한글.txt', 'euc-kr').encode('utf-8') )
IOError: [Errno 22] invalid mode ('r') or filename: '\xed\x95\x9c\xea\xb8\x80.txt'
>>打开(unicode('한글.txt“,”euc kr“)。编码('utf-8'))
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
开放式(unicode)한글.txt“,”euc kr“)。编码('utf-8'))
IOError:[Errno 22]无效模式('r')或文件名:'\xed\x95\x9c\xea\xb8\x80.txt'
但以下代码无法正常运行

>>> open( unicode('한글.txt', 'euc-kr') )
<open file u'\ud55c\uae00.txt', mode 'r' at 0x01DD63E0>
>>打开(unicode('한글.txt“,”euc kr“))

Windows向Python公开的C运行时界面使用系统代码页对文件名进行编码。与OS X和现代Linux版本不同,在Windows上,系统代码页从来都不是UTF-8。因此,UTF-8字节字符串不会有任何好处

您可以使用
.encode('mbcs')
将文件名编码到当前代码页,在您的情况下,这可能相当于
.encode('cp949')
。为了使其与文件名为UTF-8的其他平台兼容,您可以查找
sys.getfilesystemencoding
,这将为您提供
UTF-8
,或者在Windows上提供
mbcs

然而,虽然
cp949
适用于韩语字符,但它会破坏该代码页(扩展版EUC-KR)之外的任何内容

因此,另一种方法是将文件名保持为Unicode。在Windows上,这将使用Unicode本机接口以内部使用的UTF-16LE编码将文件名传递给Windows。(有关此功能的详细信息,请参见。)

这通常也适用于其他平台:Linux和OS X应该为您将Unicode文件名静默编码为UTF-8。在较旧的Python版本中,这可能会失败得更多,但这是Python3中处理文件名的默认方式(默认字符串类型已更改为Unicode)

在Python 2上使用Unicode文件名时要注意的陷阱有:

  • 如果为False,则返回文件名的函数(如
    os.listdir
    )将始终为您提供字节字符串。您必须检测到这一点,并使用
    sys.getfilesystemencoding
    对其进行解码

  • 如果您在Linux/OS X上有一个名称不是有效UTF-8字符串的文件,您将无法获取该文件的Unicode文件名(如果您尝试,则无法获取Unicode文件名)。这有点拐弯抹角,但可能会导致讨厌的无法访问的文件

顺便说一下

open(unicode('한글.txt', 'euc-kr'))
您可能想在那里说“cp949”(因为Windows韩语代码页与EUC-KR有细微的区别)。或者,更一般地说,
'mbcs'
,它为您提供系统代码页,该页面可能与您的控制台正在键入的页面相同。无论如何,我不知道PyShell的情况,但通常情况下,如果上述方法有效,那么您应该能够直接键入它:

open(u'한글')

我认为Windows使用UTF-16编码文件名。是的。。。不幸的是,这仍然有点令人头痛。Python 3对此做了一些改进。+1您似乎有很多时间和耐心来解释问题。实际上,Windows可以使用UTF-8作为系统编码(chcp 65001),但大多数应用程序都会出现错误行为。