【问题标题】:Python not able to open file with non-english characters in pathPython无法打开路径中包含非英文字符的文件
【发布时间】:2011-08-23 21:26:31
【问题描述】:

我有一个文件,路径如下:D:/bar/クレイジー・ヒッツ!/foo.abc

我正在解析 XML 文件中的路径并将其存储在名为 path 的变量中,格式为 file://localhost/D:/bar/クレイジー・ヒッツ!/foo.abc 然后,正在执行以下操作:

path=path.strip()
path=path[17:] #to remove the file://localhost/  part
path=urllib.url2pathname(path)
path=urllib.unquote(path)

错误是:

IOError: [Errno 2] No such file or directory: 'D:\\bar\\\xe3\x82\xaf\xe3\x83\xac\xe3\x82\xa4\xe3\x82\xb8\xe3\x83\xbc\xe3\x83\xbb\xe3\x83\x92\xe3\x83\x83\xe3\x83\x84\xef\xbc\x81\\foo.abc'

更新 1:我在 Windows 7 上使用 Python 2.7

【问题讨论】:

  • 那么,我该如何处理呢?
  • 尝试使用 unicode 路径字符串:path = path.decode('utf8'),在其余代码之前。
  • @Duncan - 试过了,还是不行。
  • @vr3690 您是否在 Windows 上?请您确认一下。
  • @Ignacio Vazquez-Abrams - 如何使用不同的编码?我应该在这里使用什么?

标签: python file path url-encoding


【解决方案1】:

这里有一些来自documentation 的有趣内容:

sys.getfilesystemencoding()

返回使用的编码名称 将 Unicode 文件名转换为 系统文件名,或 None 如果 使用系统默认编码。这 结果值取决于操作 系统:在 Mac OS X 上,编码是 'utf-8'。在 Unix 上,编码是 根据用户的喜好 nl_langinfo(CODESET) 的结果,或 如果 nl_langinfo(CODESET) 则无 失败的。在 Windows NT+ 上,文件名是 Unicode 本机,所以没有转换 执行。获取文件系统编码() 仍然返回“mbcs”,因为这是 应用程序应该使用的编码 当他们明确想要转换时 Unicode 字符串到字节字符串 用作文件时是等效的 名字。在 Windows 9x 上,编码是 'mbcs'。

2.3 版中的新功能。

如果我理解正确,您应该将文件名作为 unicode 传递:

f = open(unicode(path, encoding))

【讨论】:

  • 好的,我这样做了:path=unicode(path,sys.getfilesystemencoding()) 收到此错误 - TypeError: decoding Unicode is not supported
  • 我觉得路径应该已经是unicode了,所以你应该试试path.encode(encoding)
  • 好的,所以路径似乎已经是一个unicode字符串。在这种情况下,我会尝试将路径编码为 mbcs: path = path.encode(sys.getfilesystemencoding());打开(路径).read()。
  • 我玩了一下编码。虽然它解决了我最初的问题,但我现在手头有另一个问题。看看我对 MattH 另一个答案的评论
【解决方案2】:

你的错误路径是:

'\xe3\x82\xaf\xe3\x83\xac\xe3\x82\xa4\xe3\x82\xb8\xe3\x83\xbc\xe3\x83\xbb\xe3\x83\x92\xe3\x83\x83\xe3\x83\x84\xef\xbc\x81'

我认为这是您文件名的 UTF8 编码版本。

我在 Windows7 上创建了一个同名文件夹,并在其中放置了一个名为“abc.txt”的文件:

>>> a = '\xe3\x82\xaf\xe3\x83\xac\xe3\x82\xa4\xe3\x82\xb8\xe3\x83\xbc\xe3\x83\xbb\xe3\x83\x92\xe3\x83\x83\xe3\x83\x84\xef\xbc\x81'
>>> os.listdir('.')
['?????\xb7???!']
>>> os.listdir(u'.') # Pass unicode to have unicode returned to you
[u'\u30af\u30ec\u30a4\u30b8\u30fc\u30fb\u30d2\u30c3\u30c4\uff01']
>>> 
>>> a.decode('utf8') # UTF8 decoding your string matches the listdir output
u'\u30af\u30ec\u30a4\u30b8\u30fc\u30fb\u30d2\u30c3\u30c4\uff01'
>>> os.listdir(a.decode('utf8'))
[u'abc.txt']

看来邓肯对path.decode('utf8') 的建议起到了作用。


更新

我无法为您测试,但我建议您在执行 .decode('utf8') 之前尝试检查路径是否包含非 ascii。这有点hacky...

ASCII_TRANS = '_'*32 + ''.join([chr(x) for x in range(32,126)]) + '_'*130
path=path.strip()
path=path[17:] #to remove the file://localhost/  part
path=urllib.unquote(path)
if path.translate(ASCII_TRANS) != path: # Contains non-ascii
  path = path.decode('utf8')
path=urllib.url2pathname(path)

【讨论】:

  • 确实如此。但是,又引发了另一个问题。我终于使用以下代码为自己获取了一个可用的路径:` path=urllib.unquote(path) path=path.decode('utf8') path=urllib.url2pathname(path) ` 这导致了这个错误:@ 987654326@ 知道这条路径可能有什么问题吗?
  • @vr3690,可能更容易开始一个新问题并从那里开始。
  • 哎呀。原来我正在处理一些旧数据。该文件实际上不存在并被删除。但我真的认为你更新的代码是要走的路。非常感谢您的帮助!
  • @vr3690:我希望你给自己一个友好的耳光,因为你不是伸手可及的。答案原来是邓肯的评论/建议,你说没有用,你的第二个问题是文件实际上并不存在。这些事情不会让你成为一个容易提供帮助的人。
【解决方案3】:

将文件名作为unicode 字符串提供给open 调用。

你如何产生文件名?

如果您作为常量提供

在脚本开头附近添加一行:

# -*- coding: utf8 -*-

然后,在支持 UTF-8 的编辑器中,将 path 设置为 unicode 文件名:

path = u"D:/bar/クレイジー・ヒッツ!/foo.abc"

从目录内容列表中读取

使用unicode dirspec 检索目录的内容:

dir_files= os.listdir(u'.')

从文本文件中读取

使用codecs.open 打开包含文件名的文件以从中读取unicode 数据。您需要指定文件的编码(因为您知道计算机上非 Unicode 应用程序的“默认 windows 字符集”是什么)。

无论如何

做一个:

path= path.decode("utf8")

在打开文件之前;如果不是“utf8”,则替换正确的编码。

【讨论】:

  • 确实如此。但是,又引发了另一个问题。我终于使用以下代码为自己获取了一个可用的路径:` path=urllib.unquote(path) path=path.decode('utf8') path=urllib.url2pathname(path) ` 这导致了这个错误:IOError : [Errno 2] 没有这样的文件或目录:u'D:\\Music\\Pink Floyd\\The Wall Disc 1\\5 - Another Brick in the Wall, Pt. 2.mp3' 知道这条路径可能有什么问题吗?
  • 弗洛伊德粉丝的任何东西 :) 在open 之前,请先print(repr(path)) 确保反斜杠尽可能多。回这里发帖。
  • @ΤZΩΤZΙΟΥ 啊。弗洛伊德。给你 - u'D:\\Music\\Pink Floyd\\The Wall Disc 1\\5 - Another Brick in the Wall, Pt. 2.mp3'
  • 原来,该文件实际上并不存在。我正在处理一些旧数据。非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2015-05-10
  • 2020-03-16
  • 2016-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多