Python 编码问题。替换特殊字符

Python 编码问题。替换特殊字符,python,python-2.7,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) 我怎样才能解决这个问题 现在编码是一个雷区,我可能会在这一个上关闭-如果是这样,请纠正

我有一本这样的字典:

{ u'Samstag & Sonntag': u'Ganztags ge\xf6ffnet', u'Freitag': u'18:00 & 22:00'}
现在我试图用
ö
替换
\xf6
, 但是尝试
.replace('\xf6','ö')
会返回一个错误:

UnicodeDecodeError:“ascii”编解码器无法解码位置中的字节0xf6 0:序号不在范围内(128)


我怎样才能解决这个问题

现在编码是一个雷区,我可能会在这一个上关闭-如果是这样,请纠正我

从我多年来收集的信息来看,除非在脚本顶部定义了编码,否则Python2采用ASCII。主要是因为它是以这种方式编译的,或者OS/终端使用ASCII作为主要编码

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

{ u'Samstag & Sonntag': u'Ganztags ge\xf6ffnet', u'Freitag': u'18:00 & 22:00'}
是unicode字符串的ASCII表示形式。Python需要告诉您其中有一个
ö
,但它不能使用ASCII,因为
ö
在中没有表示。

但当您尝试使用以下方法替换它时:

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中您遇到的大多数字符串要么是
字节
数据,要么与Python2的处理方式稍有不同。在大多数情况下,这要容易得多

这不是标准实践的一部分,但有办法做到这一点。
最接近“良好”实践的是:

几年前,我也有一个可怕的解决方案和方法,它看起来像这样(这在当时对我来说是个好兆头):

tl;dr: 您的代码通常假定/使用ASCII作为编码器/解码器。

ö
不是ASCII的一部分,如果你有一些如何获得unicode字符,你总会看到
\xf6
。通常,如果你打印
u'Ganztags ge\xf6ffnet'
,由于自动编码,它将显示为Ö,如果你需要验证输入是否与该字符串匹配,你必须比较它们de>,如果其他系统依赖于此数据,请使用他们理解的内容对其进行编码。
.encode('UTF-8')
。但是将
\xf6
替换为
ö
是一样的,只是
ö
在ASCII中不存在,您需要执行
u'ö'
-这将在最后产生相同的数据。

当您使用德语时,您应该注意非ASCII字符。您知道您的系统首选Latin1(Windows控制台和一些Unix)、UTF8(大多数Linux变体)或本机unicode(Windows GUI)

如果您可以将所有内容都作为原生unicode处理,那么事情就更干净了,您应该接受这样一个事实,即
u'ö'
u'\xf6'
是同一个字符,后者与python源文件字符集无关

如果必须输出存储在文件中的字节字符串,则应使用UTF8(可以处理任何unicode字符,但127以上的代码字符使用超过1字节)或拉丁语1(每个字符一个字节,但仅支持256以下的unicode代码点)对其进行编码

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

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

应该给出您所期望的。

这很可能是Python2。但是您最好标记您的问题或提及您正在使用的Python版本。因为Python2和Python3在解码部门有很大不同。这个问题是因为默认情况下,unicode字符串将使用ASCII解码,因为使用未定义的在脚本中编码,然后在替换调用中将ASCII替换为ASCII..IIRC.您是如何以
u'
字符串中的
\xf6
作为开头的…?
u'\xf6'
u'ö
len(u'\xf6'非常相似)==1
u'\xf6'==u'ö'
这里的评论者都疯了吗?你不需要替换任何东西!
。替换(u'\xf6',u'ö)
是不可操作的。您使用的是什么操作系统?您的终端使用的是什么编码?您的终端中显示的是什么?取决于您的设置,您可以直接打印Unicode对象,否则您需要进行适当的编码,例如
打印u'Ganztags ge\xf6ffnet'。编码('utf8')
打印u'Ganztags ge\xf6ffnet'.encode('latin1'))
.Character
ö
具有unicode和8位拉丁1编码的code
\xf6
,也称为iso-8859-1。Python支持不同的8位编码,拉丁1在西欧语言(包括德语)中很常见。@SergeBallesta这是您现在谈论的扩展ASCII表,对吗?因为默认值
128位表(我想是的)不支持。Python支持大约30位
print u'Ganztags ge\xf6ffnet'.encode('Latin1') # or .encode('utf8')