当前位置: 首页 > 面试题库 >

执行os.walk时出现UnicodeDecodeError

谭毅然
2023-03-14
问题内容

我收到错误消息:

'ascii' codec can't decode byte 0x8b in position 14: ordinal not in range(128)

尝试做os.walk时。发生错误是因为目录中的某些文件中包含0x8b(非UTF8)字符。这些文件来自Windows系统(因此为utf-16文件名),但是我已将文件复制到Linux系统中,并且正在使用python
2.7(在Linux中运行)遍历目录。

我尝试将unicode起始路径传递给os.walk,并且它生成的所有文件和目录都是unicode名称,直到涉及到非utf8名称为止,然后由于某种原因,它不会将这些名称转换为unicode和然后代码使utf-16名称阻塞。除了手动查找和更改所有令人反感的名字以外,还有解决问题的方法吗?

如果python2.7中没有解决方案,是否可以在python3中编写脚本来遍历文件树并通过将错误的文件名转换为utf-8(通过删除非utf8字符)来修复错误的文件名?注意,除了0x8b之外,名称中还有许多非utf8字符,因此需要以常规方式工作。

更新:0x8b仍然只是一个btye字符(只是无效的ascii)这一事实使它更加令人困惑。我已经验证了将这样的字符串转换为unicode时存在问题,但是可以直接创建unicode版本。以机智:

>>> test = 'a string \x8b with non-ascii'
>>> test
'a string \x8b with non-ascii'
>>> unicode(test)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0x8b in position 9: ordinal not in  range(128)
>>> 
>>> test2 = u'a string \x8b with non-ascii'
>>> test2
u'a string \x8b with non-ascii'

这是我得到的错误的追溯:

80.         for root, dirs, files in os.walk(unicode(startpath)):
File "/usr/lib/python2.7/os.py" in walk
294.             for x in walk(new_path, topdown, onerror, followlinks):
File "/usr/lib/python2.7/os.py" in walk
294.             for x in walk(new_path, topdown, onerror, followlinks):
File "/usr/lib/python2.7/os.py" in walk
284.         if isdir(join(top, name)):
File "/usr/lib/python2.7/posixpath.py" in join
71.             path += '/' + b

Exception Type: UnicodeDecodeError at /admin/casebuilder/company/883/
Exception Value: 'ascii' codec can't decode byte 0x8b in position 14: ordinal not in range(128)

问题的根源出现在从listdir返回的文件列表中(在os.walk的第276行):

names = listdir(top)

字符> 128的名称将作为非Unicode字符串返回。


问题答案:

这个问题源于两个基本问题。第一个事实是Python 2.x的默认编码为’ascii’,而Linux的默认编码为’utf8’。您可以通过以下方式验证这些编码:

sys.getdefaultencoding() #python
sys.getfilesystemencoding() #OS

当os模块函数返回目录内容(即os.walk和os.listdir)返回仅包含ascii文件名和非ascii文件名的文件列表时,ascii编码文件名将自动转换为unicode。其他不是。因此,结果是一个包含unicode和str对象混合的列表。正是str对象可能会导致问题。由于它们不是ascii,因此python无法知道要使用哪种编码,因此无法将它们自动解码为unicode。

因此,当执行诸如os.path(dir,file)之类的常用操作时,其中 dir 是unicode,而 file
是已编码的str,如果文件未进行ascii编码(默认设置),则此调用将失败。解决方案是在检索到每个文件名后立即检查它们,并使用适当的编码将str(已编码的)对象解码为unicode。

那是第一个问题及其解决方案。第二个有点棘手。由于文件最初来自Windows系统,因此它们的文件名可能使用称为 Windows-1252
的编码。一种简单的检查方法是致电:

filename.decode('windows-1252')

如果结果是有效的unicode版本,则您可能具有正确的编码。您也可以通过在unicode版本上调用 print 进一步进行验证,并查看正确的文件名。

最后的皱纹。在具有Windows起源文件的Linux系统中,可能甚至可能混合使用 Windows-1252utf8
编码。有两种处理这种混合的方法。首先,最好是运行:

$ convmv -f windows-1252 -t utf8 -r DIRECTORY --notest

其中DIRECTORY是包含需要转换的文件的目录。此命令会将所有Windows-1252编码的文件名转换为utf8。它进行了智能转换,如果文件名已经是utf8(或ascii),它将什么都不做。

另一种方法(如果由于某种原因而无法执行此转换)是在python中即时执行类似的操作。以机智:

def decodeName(name):
    if type(name) == str: # leave unicode ones alone
        try:
            name = name.decode('utf8')
        except:
            name = name.decode('windows-1252')
    return name

该函数首先尝试utf8解码。如果失败,则回退到Windows-1252版本。在os调用返回文件列表之后使用此功能:

root, dirs, files = os.walk(path):
    files = [decodeName(f) for f in files]
    # do something with the unicode filenames now

我个人发现unicode和编码的整个主题都非常混乱,直到我阅读了这个精彩而简单的教程

http://farmdev.com/talks/unicode/

我极力推荐给任何遇到u​​nicode问题的人。



 类似资料:
  • 问题内容: 我有带有库的IntelliJ项目:Hibernate-entitymanager 4.3.4和JPA 2.0-2.0。使用postgresql-9.3.1100.jdbc4连接到数据库。如何解决? jpa-ql>从ItemEntity中选择ItemEntity.name; 问题答案: 只需阅读文档: http://docs.oracle.com/javaee/7/api/javax/p

  • 问题内容: 这是代码 错误回溯为: 似乎struct.unpack方法将’\ xff '解析为255并分配给,无论传递的非null字符集参数如何。 这是MySQL版本问题吗?(版本) 问题答案: 可以参考 拉取请求591

  • 我试图在包含GUI系统的JDK 11.0.2上运行我在Intellij中创建的一个可执行jar文件。我已经安装了Java8和java SDK11.0.2。每当我双击jar文件时,我希望主gui登录屏幕出现,但什么也没有发生。我已经尝试了其他选项,例如尝试通过cmd运行它(它给了我一个访问错误),HKEY_CLASSES_ROOT\jarfile已经有命令:“C:\Program Files\jav

  • 我正在尝试让nutch 1.11执行爬网。我正在使用cygwin在windows 7中运行这些命令。 Nutch正在运行,运行bin/Nutch会得到结果,但当我尝试运行爬网时,会不断收到错误消息。 当我尝试使用 nutch 运行爬网执行时,我收到以下错误: 运行时出错:/cygdrive/c/Users/User5/Documents/Nutch/apache-Nutch-1.11/runtim

  • 我刚遇到这个错误,它突然来了,破坏了我的项目。有没有人可以帮助我解决这个错误:

  • 突然我开始得到这个错误,我不明白为什么如果有人让我知道这个错误在哪里,会有足够的帮助。因为android Studio的新更新,我能得到的就是这个。我得到的错误的详细摘要。