编码问题。替换特殊字符

时间:2017-01-18 15:12:13

标签: python python-2.7

我的字典看起来像这样:

{ u'Samstag & Sonntag': u'Ganztags ge\xf6ffnet', u'Freitag': u'18:00 & 22:00'}

现在我正在尝试将\xf6替换为ö, 但尝试.replace('\xf6', 'ö')会返回错误:

  

UnicodeDecodeError:'ascii'编解码器无法将字节0xf6解码到位   0:序数不在范围内(128)

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

现在编码是一个雷区,我可能会关注这个 - 如果是这样的话,请纠正我。

多年来我收集的是Python2假设ASCII,除非你在脚本的顶部定义了一个编码。主要是因为它是以这种方式编译的,或者OS /终端使用ASCII作为它的主要编码。

话虽如此,您在示例数据中看到的内容:

{ u'Samstag & Sonntag': u'Ganztags ge\xf6ffnet', u'Freitag': u'18:00 & 22:00'}

是unicode字符串的ASCII表示。有些Python需要告诉你那里有一个ö - 但它不能用ASCII,因为öASCII table中没有任何表示。

但是当你尝试使用:

替换它时
x.replace('\xf6', 'ö')

您正在尝试查找名为\xf6的ASCII字符/字符串,该字符/字符串超出了ASCII的可接受字节范围,因此会引发异常。并且您正在尝试将其替换为另一个无效的ASCII字符,这将导致相同的异常。

因此,为什么你得到“'ascii'编解码器无法解码字节...'消息。

您可以像这样执行unicode替换:

a = u'Ganztags ge\xf6ffnet'
a.replace(u'\xf6', u'ö')

这将告诉Python找到一个unicode字符串,并用另一个unicode字符串替换它 但是输出数据在上面的示例中会产生相同的结果,因为\xf6在unicode中是ö

您想要做的是将您的字符串编码为您想要使用的内容,例如 - UTF-8:

a.encode('UTF-8')
'Ganztags ge\xc3\xb6ffnet'

将UTF-8定义为您的主要编码,方法是将其放在代码的顶部:

#!/usr/bin/python
# -*- coding: UTF-8

理论上,这应该使您的应用程序更容易使用 从那时起,您可以使用UTF-8作为基础模型。

但我不知道将表示转换为ASCII ö,因为实际上并没有这样的东西。只有不同的方式,Python会为你做这个编码魔术,让你相信它可以“只写ö”。

在Python3 中,您遇到的大多数字符串都是bytes数据,或者与Python2略有不同。在大多数情况下,它更容易。

numerous ways to change the encoding不是标准实践的一部分。但是有办法做到这一点 最接近“好”的实践,将是locale

locale.setlocale(locale.LC_ALL, 'sv_SE.UTF-8')

这几年我也有一个可怕的解决方案和方法,它看起来像这样(当时对我来说这是一个很棒的小屋):

TL; DR:

您的代码通常假定/使用ASCII作为编码器/解码器 ö不是ASCII的一部分,如果你有一些如何获得unicode字符,你总会看到\xf6。通常情况下,如果您打印u'Ganztags ge\xf6ffnet',由于自动编码,它将显示为Ö,如果您需要验证输入是否与该字符串匹配,则必须比较它们u'ö' == u'ö',如果其他系统依赖于此数据,用他们理解的东西.encode('UTF-8')编码。但是将\xf6替换为ö是一回事,只是ö在ASCII中不存在而您需要执行u'ö' - 这将导致相同的数据最后。

答案 1 :(得分:0)

当您使用德语时,您应该注意非ascii字符。 知道您的系统是否更喜欢Latin1(Windows控制台和某些Unix),UTF8(大多数Linux版本)或本机unicode(Windows GUI)。

如果您可以处理所有内容,因为本机unicode事物更清晰,您应该接受u'ö'u'\xf6'是相同字符的事实 - 后者只是独立于python源文件字符集。

如果你必须输出将它们存储在文件中的字节字符串,你应该用UTF8 编码它们(可以处理任何unicode字符但127以上代码的字符使用超过1个字节)或Latin1(每个字符一个字节,但仅支持低于256的unicode代码点

在这种情况下,只需使用显式编码将unicode字符串转换为字节字符串:

print u'Ganztags ge\xf6ffnet'.encode('Latin1') # or .encode('utf8')

应该给出你期望的东西。