Python 3: os.walk() 文件路径 UnicodeEncodeError: 'utf-8' codec can't encode: surrogates not allowed

Posted

技术标签:

【中文标题】Python 3: os.walk() 文件路径 UnicodeEncodeError: \'utf-8\' codec can\'t encode: surrogates not allowed【英文标题】:Python 3: os.walk() file paths UnicodeEncodeError: 'utf-8' codec can't encode: surrogates not allowedPython 3: os.walk() 文件路径 UnicodeEncodeError: 'utf-8' codec can't encode: surrogates not allowed 【发布时间】:2015-02-06 14:37:31 【问题描述】:

这段代码:

for root, dirs, files in os.walk('.'):
    print(root)

给我这个错误:

UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc3' in position 27: surrogates not allowed

如何遍历文件树而不得到这样的有毒字符串?

【问题讨论】:

python 3 的哪个版本? Python 3.4.0(默认,2014 年 4 月 11 日,13:05:11)在 Ubuntu 14.04 上。我有LANG=en_US.UTF-8 print(root.encode("utf-8", "surrogateescape"))有什么作用吗? ***.com/questions/38147259/… 对错误消息的含义进行了更详细的解释。 【参考方案1】:

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

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

>>> b'C\xc3N'.decode('utf8','surrogateescape')
'C\udcc3N'

可以无损地与Unicode相互转换:

>>> b'C\xc3N'.decode('utf8','surrogateescape').encode('utf8','surrogateescape')
b'C\xc3N'

但是不能打印:

>>> 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

您必须弄清楚要如何处理具有非默认编码的文件名。也许只是将它们编码回原始字节并用未知的替换解码它们。使用它进行显示,但保留原始名称以访问文件。

>>> b'C\xc3N'.decode('utf8','replace')
C�N

os.walk 也可以接受字节字符串,并且将返回字节字符串而不是 Unicode 字符串:

for p,d,f in os.walk(b'.'):

然后你就可以随意解码了。

【讨论】:

我最终做了bad_string.encode('utf-8', 'surrogateescape').decode('ISO-8859-1') @Collin Anderson 您是如何检测到错误字符串的出现,您是如何捕获错误的? 对我有用的是"bad string".encode('utf-8', 'surrogateescape').decode('utf-8') 你获得支持,Python 为格兰芬多获得 -10 分。 @DoTheEvo Collins hack 适用于好字符串和坏字符串。它之所以有效,是因为每个字节都是“ISO-8859-1”中的有效代码点。但是,对于没有相同 utf-8 和 'ISO-8859-1' 编码的字符,它会打印出奇怪的东西。【参考方案2】:

我最终将一个字节字符串传递给 os.walk(),这显然会返回字节字符串而不是不正确的 unicode 字符串

for root, dirs, files in os.walk(b'.'):
    print(root)

【讨论】:

【参考方案3】:

尝试使用这行代码:

"bad string".encode('utf-8', 'replace').decode()

【讨论】:

【参考方案4】:

使用sedgrep 过滤:

set | sed -n '/^[a-zA-Z0-9_]*=/p'
# ... or ...
set | grep '^[a-zA-Z0-9_]*='
# ... or ...
set | egrep '^[_[:alnum:]]+='

这对你的变量名有多疯狂很敏感。最后一个版本应该可以处理最疯狂的事情。

【讨论】:

以上是关于Python 3: os.walk() 文件路径 UnicodeEncodeError: 'utf-8' codec can't encode: surrogates not allowed的主要内容,如果未能解决你的问题,请参考以下文章

python os.walk()

python学习之os.walk()

Python3.x:os.listdir和os.walk(获取路径方法)的区别

Python入门之os.walk()方法

Python os.walk

Python os.walk文件遍历