Python 3:os.walk()文件路径UnicodeEncodeError:'utf-8'编解码器无法编码:不允许代理

Col*_*son 16 python unicode unicode-string python-3.x python-unicode

这段代码:

for root, dirs, files in os.walk('.'):
    print(root)
Run Code Online (Sandbox Code Playgroud)

给我这个错误:

UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc3' in position 27: surrogates not allowed
Run Code Online (Sandbox Code Playgroud)

如何在没有像这样的有毒字符串的情况下浏览文件树?

Mar*_*nen 28

在Linux上,文件名只是"一堆字节",并不一定用特定的编码进行编码.Python 3试图将所有内容都转换为Unicode字符串.在这样做的过程中,开发人员提出了一种方案,将字节字符串转换为Unicode字符串并返回而不会丢失,并且不知道原始编码.他们使用部分代理来编码'坏'字节,但普通的UTF8编码器在打印到终端时无法处理它们.

例如,这是一个非UTF8字节字符串:

>>> b'C\xc3N'.decode('utf8','surrogateescape')
'C\udcc3N'
Run Code Online (Sandbox Code Playgroud)

它可以转换为Unicode而不会丢失:

>>> b'C\xc3N'.decode('utf8','surrogateescape').encode('utf8','surrogateescape')
b'C\xc3N'
Run Code Online (Sandbox Code Playgroud)

但它不能打印:

>>> print(b'C\xc3N'.decode('utf8','surrogateescape'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc3' in position 1: surrogates not allowed
Run Code Online (Sandbox Code Playgroud)

你必须弄清楚你想用非默认编码对文件名做什么.也许只是将它们编码回原始字节并使用未知替换解码它们.使用此选项进行显示,但保留原始名称以访问该文件.

>>> b'C\xc3N'.decode('utf8','replace')
C?N
Run Code Online (Sandbox Code Playgroud)

os.walk 也可以采用字节字符串,并返回字节字符串而不是Unicode字符串:

for p,d,f in os.walk(b'.'):
Run Code Online (Sandbox Code Playgroud)

然后你可以随意解码.

  • 我最后做了'bad_string.encode('utf-8','surrogateescape').decode('ISO-8859-1')` (6认同)
  • 对我有用的是 `"bad string".encode('utf-8', 'surrogateescape').decode('utf-8')` (4认同)

小智 17

尝试使用这行代码:

"bad string".encode('utf-8', 'replace').decode()
Run Code Online (Sandbox Code Playgroud)


Col*_*son 6

我最终传入一个字节字符串os.walk(),显然会返回字节字符串而不是错误的unicode字符串

for root, dirs, files in os.walk(b'.'):
    print(root)
Run Code Online (Sandbox Code Playgroud)