为什么我会在一个案例中获得此unicode警告而不是另一个案例?

时间:2014-03-27 17:57:09

标签: python unicode

在这里使用python 2.7 ......

我正在编码/解码一个字符串(实际上是一个字符),但是我收到一个警告:

enc.py:22: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal

评估读取的行:“if(b == c)”。这是python代码和我的输出。我想如果我得到“if(b == c)”比较的警告我也会收到“if(a == c)”比较,但我没有。为什么呢?

a = "A"
b = a.encode("utf16")
c = b.decode("utf16")

print "Unencoded len(a) = " + str(len(a))
print "utf16 encoded len(a) = " + str(len(b))
print "decoded utf16 length = " + str(len(c))

print ""
print "type(a) = " + str(type(a))
print "type(b) = " + str(type(b))
print "type(c) = " + str(type(c))
print ""

if (b == a):
    print " a = b"
else:
    print " a != b"

if (b == c):
    print " b = c"
else:
    print " b != c"

if (a == c):
    print " a = c"
else:
    print " a != c"

这是我的输出:

Unencoded len(a) = 1
utf16 encoded len(a) = 4
decoded utf16 length = 1

type(a) = <type 'str'>
type(b) = <type 'str'>
type(c) = <type 'unicode'>

 a != b
enc.py:22: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
  if (b == c):
 b != c
 a = c

4 个答案:

答案 0 :(得分:0)

如果您还没有看到它,这是一篇关于Python中Unicode的非常精彩的演讲/教程:

http://nedbatchelder.com/text/unipain.html

Python 2在幕后做了一些魔术,并试图来回自动转换unicode / ascii。我相信.encode()创建一个bytestring,而.decode()将它转换回utf8 / ascii。

所以b是string类型,但它是一个编码字符串。我相信正在发生的事情(有人请纠正我,如果我错了,Unicode会让我的头受伤)是这样的:

a = ascii

b =

的bytestring版本

c =

的unicode版本

Python认为a和b(以及b和c)是不同的,但是然后将c自动转换回ascii(或a到unicode)并认为它们匹配。

我敢打赌,Python 3会抱怨== c,因为它会更仔细地跟踪这种区别。

答案 1 :(得分:0)

嗯,这很可能是因为它在比较a和c之前转换c。我认为这是预期的行为。它在警告中说它正在尝试转换。

答案 2 :(得分:0)

此错误意味着您实际上并未比较两个unicode对象,而是将字符串对象与unicode对象进行比较。

尝试:

print type(a), type(b), type(c)

你会看到结果:

<type 'str'> <type 'str'> <type 'unicode'>

解决方案是将您要比较的内容转换为相同类型(有关详细信息,请查看unicode)。

希望这会有所帮助。

答案 3 :(得分:0)

简而言之:当您通过将b编码为utf-16创建a时,您将创建一个非ascii字符串。 Python没有跟踪其内容的来源,所以当以后需要将b转换为unicode时,它不知道应如何解释其内容。

详情

Python有两种存储文本的方式:作为unicode字符,其属性由python已知和理解,或作为字节序列。后者描述了python 2中的类型str,它在python 3中被重命名为更合适的bytes(并且unicode成为文本字符串的默认格式)。

第一次转换b = a.encode("utf16")成功,因为当python 2在字符串中找到类似ASCII文本的字节(序号值低于255的字符)时,它假定它们 ascii文本。

就python而言, b不是unicode文本。它包含一个表示utf16编码字符的4字节序列,但 python不跟踪其中字节序列来自。因此,当您通过将b与unicode字符串进行比较来触发自动转换为unicode时,python会注意到它不是纯ASCII但不知道要使用哪种编码。

当然,您可以通过明确标识编码将b转换为unicode,就像创建c时所做的那样:

c = b.decode("utf16")