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】:使用sed
或grep
过滤:
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的主要内容,如果未能解决你的问题,请参考以下文章