Python字符串比较--特殊/Unicode字符的问题

Python字符串比较--特殊/Unicode字符的问题,python,string,Python,String,我正在编写一个Python脚本来处理一些音乐数据。它应该通过比较两个独立的数据库的条目并进行匹配来合并它们。它几乎可以工作,但在比较包含特殊字符(即重音字母)的字符串时失败。我很确定这是ASCII与Unicode编码的问题,因为我得到了错误: “Unicode相等比较无法将两个参数转换为Unicode-将它们解释为不相等” 我意识到我可以使用正则表达式来删除有问题的字符,但是我正在处理大量的数据,并且过多地依赖正则表达式使得我的程序非常慢。有没有办法让Python正确地比较这些字符串?这里发生了

我正在编写一个Python脚本来处理一些音乐数据。它应该通过比较两个独立的数据库的条目并进行匹配来合并它们。它几乎可以工作,但在比较包含特殊字符(即重音字母)的字符串时失败。我很确定这是ASCII与Unicode编码的问题,因为我得到了错误:

“Unicode相等比较无法将两个参数转换为Unicode-将它们解释为不相等”


我意识到我可以使用正则表达式来删除有问题的字符,但是我正在处理大量的数据,并且过多地依赖正则表达式使得我的程序非常慢。有没有办法让Python正确地比较这些字符串?这里发生了什么——有没有办法判断它是将字符串存储为ASCII还是Unicode

编辑1:我正在使用Python v2.6.6。在检查类型之后,我发现一个数据库向我输出Unicode字符串,另一个提供ASCII。这可能就是问题所在。我正在尝试将第二个数据库中的ASCII字符串转换为Unicode,代码行如下

line = unicode(f.readline().decode(latin_1).encode(utf_8))
但这会产生如下错误:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 41: ordinal not in range(128)

我不知道为什么“ascii”编解码器会抱怨,因为我试图从ascii解码。有人能帮忙吗?

您可能需要预处理数据库并将所有内容转换为UTF-8。我猜你在一些条目中有拉丁-1重音字符。

至于你的问题,唯一确定的方法就是看。让你的脚本吐出那些没有比较的,并查找字符代码。或者尝试
string.decode('latin1')。encode('utf8')
看看会发生什么。

将两者转换为unicode应该会有帮助:

if unicode(str1) == unicode(str2):
    print "same" 
要了解您(不是it)是将字符串存储为
str
对象还是
unicode
对象,请使用
打印类型(您的字符串)

您可以使用
print repr(您的_字符串)
清楚地显示您自己(和我们)的字符串内容


顺便问一下,您在什么操作系统上使用的是什么版本的Python?如果使用Python 3.x,请使用
ascii()
而不是
repr()

Unicode vs Bytes

首先是一些术语。有两种类型的字符串,编码和解码:

  • 编码的。这是存储在磁盘上的内容。对于Python来说,它是一组0和1,可以像ASCII一样处理,但它可以是任何东西——二进制数据、JPEG图像,等等。在Python2.x中,这称为“字符串”变量。在Python3.x中,它更准确地称为“bytes”变量
  • 解码。这是一个实际字符的字符串。它们可以编码为8位ASCII字符串,也可以编码为32位汉字。但在转换为编码变量之前,它只是一个Unicode字符串
这对你意味着什么

事情是这样的。你说你得到一个ASCII变量和一个Unicode变量。事实并非如此

  • 有一个变量是一个字节串——1和0,大概是8的集合。这是您错误地假定为ASCII的变量
  • 还有一个变量是Unicode数据——数字、字母和符号
在将字节字符串与Unicode字符字符串进行比较之前,必须进行一些假设。在您的例子中,Python(和您)假设字节字符串是ASCII编码的。这很好,直到你遇到一个非ASCII字符——一个带有重音符号的字符

所以你需要找出这个字节串被编码成什么。可能是拉丁语。如果是,则要执行以下操作:

if unicode_variable == string_variable.decode('latin1')
Latin1基本上是ASCII加上一些扩展字符,如CHU和

如果您的数据是拉丁文1,那么您只需要这样做。但是,如果您的字节字符串是以其他形式编码的,那么您需要弄清楚这是什么编码,并将其传递给decode()

底线是,没有简单的答案,除非您知道(或做出一些假设)输入数据的编码

我会做什么

尝试在字节串上运行var.decode('latin1')。这将为您提供一个Unicode变量。如果这样做有效,并且数据看起来是正确的(即,带有重音标记的字符看起来像是它们所属的),那么使用它


哦,如果latin1无法解析或看起来不正确,请尝试utf8——另一种常见的编码。

嗯。。。看起来到unicode的隐式转换失败了;让它显式转换会有帮助吗?OP应该如何“吐出”字符串?什么字符码?查什么?是什么让你认为OP的文本编码是拉丁文1,或者他的系统的默认编码是拉丁文1?.encode('utf8')的意义是什么???[如果解码成功,您将获得unicode,它保证不会以UTF-8编码失败]这是一个很大的问题。我所说的“吐出”是指在测试中使用try/except,并将导致错误的任何内容打印到stderr。如果我看到类似“\xc3\xbcmlaut\n”的内容,我会有一些有用的诊断信息。您关于编码('utf8')的观点很好,我认为这还不够。如果您将其重新编码为utf8,那么您可以返回到将Unicode变量与字节字符串进行比较。正确的做法是比较两个已解码的unicode变量。如果对两个字符串都执行相同的操作,则不会这样做。但你是对的,重新编码不是正确的做法。正如我所说,“我想得不够透彻”。我最近用Python转换我的iPod Touch音乐数据库时遇到了拉丁字符编码问题。“使用正则表达式删除冒犯的字符”:在知道冒犯的字符是什么以及为什么冒犯之前,是不可能的,删除不方便的数据通常不是一个好主意。解决方案更可能是使用正确的编码对
str
对象进行解码。谢谢,成功了!我