如何在Python中替换字符串中的无效Unicode字符?

7
据我所知,Python的概念是字符串中只包含有效字符,但在我的情况下,操作系统将提供带有无效编码的路径名字符串,我必须处理这些字符串。因此,我最终得到了包含非unicode字符的字符串。
为了解决这些问题,我需要以某种方式显示这些字符串。不幸的是,我无法打印它们,因为它们包含非unicode字符。是否有一种优雅的方法来替换这些字符,以至少获得字符串内容的一些想法?
我的想法是逐个处理这些字符串中的字符,并检查存储的字符是否实际为有效的unicode。对于无效字符,我想使用某个unicode符号。但是,我该如何做呢?使用codecs似乎不适合此目的:我已经有一个由操作系统返回的字符串,而不是字节数组。将字符串转换为字节数组似乎涉及到解码,这显然会失败。所以看起来我陷入了困境。
你有什么建议可以帮助我创建这样一个替换字符串吗?
4个回答

15

如果你有一个字节串(未解码的数据),请使用 'replace' 错误处理程序。例如,如果你的数据(大多数)是 UTF-8 编码的,则可以使用:

decoded_unicode = bytestring.decode('utf-8', 'replace')

对于无法解码的任何字节,都会插入 U+FFFD � 替换字符

如果您想使用不同的替换字符,稍后可以轻松更改:

decoded_unicode = decoded_unicode.replace('\ufffd', '#')

示例:

>>> bytestring = b'F\xc3\xb8\xc3\xb6\xbbB\xc3\xa5r'
>>> bytestring.decode('utf8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf8' codec can't decode byte 0xbb in position 5: invalid start byte
>>> bytestring.decode('utf8', 'replace')
'Føö�Bår'

不错!我在文档中没有看到这个:我希望这样的功能能更加突出地描述。 - Regis May

5
感谢您的评论。通过您的建议,我得以实现更好的解决方案:
    try:
        s2 = codecs.encode(s, "utf-8")
        return (True, s, None)
    except Exception as e:
        ret = codecs.decode(codecs.encode(s, "utf-8", "replace"), "utf-8")
        return (False, ret, e)

请分享对该解决方案的任何改进。谢谢!

1
您没有提供例子。因此,我考虑了一个例子来回答您的问题。
x='This is a cat which looks good 😊'
print x
x.replace('😊','')

输出结果为:
This is a cat which looks good 😊
'This is a cat which looks good '

我没有关于实际字节模式的具体例子,导致了我的情况中出现错误。我正在编写的过滤器旨在识别给定字符串中的Unicode编码问题。您可能能够重现这种情况的一种方法是简单地生成随机数据,然后尝试将此数据解释为UTF-8。通常会失败,因为这些二进制数据很可能违反UTF-8标准。很抱歉,我无法确定这些违规行为是如何发生的。我试图首先确认它们的存在。 - Regis May
如果你不知道非Unicode字符,可以尝试以下代码: try: string.decode('utf-8') print "字符串是UTF-8编码,长度为%d字节" % len(string) except UnicodeError: print "字符串不是UTF-8编码" - Chandan
是的,但有趣的部分开始于我不仅想识别字符串是否为Unicode,而且想通过过滤或替换无效的“字符”来实际了解字符串本身的一些信息。 - Regis May
如果您能够识别无效的单词,那么您只需替换该单词。 - Chandan

1

正确的方法(至少在Python2中)是使用unicodedata.normalize:

unicodedata.normalize('NFKD', text).encode('utf-8', 'ignore')

decode('utf-8', 'ignore') 只会引发异常。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接