为什么unicode(u'')传递了一个错误参数引发TypeError

时间:2014-02-20 03:46:05

标签: python python-2.7 unicode python-unicode

使用python 2.7.3,以下内容不会引发TypeError。

>>> unicode(u'')
    u''

但是传递errors参数会引发TypeError: decoding Unicode is not supported

>>> unicode(u'',errors='replace')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: decoding Unicode is not supported

>>> unicode(u'',errors='ignore')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: decoding Unicode is not supported

>>> unicode(u'',errors='strict')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: decoding Unicode is not supported

任何猜测为什么这种行为如此不同? IMO,这是unicode函数的一个令人惊讶的怪癖。


浏览python源代码,(我只是猜测我正在遵循正确的代码路径)

    在函数PyUnicode_FromEncodedObject的{​​{3}}中
  1. ,我们找到错误字符串"decoding Unicode is not supported"。如果PyUnicode_Check(obj)返回非0,则设置错误字符串。

  2. <{3}}中的
  3. PyUnicode_Check评估表达式(((Py_TYPE(obj))->tp_flags & (Py_TPFLAGS_UNICODE_SUBCLASS)) != 0)

  4. 但是,由于传递了errors参数,我无法找到Python代码采用不同代码路径的位置。

2 个答案:

答案 0 :(得分:2)

Python中的

unicodedocs)是一个将字符串转换为Python中字符串的unicode表示的函数。但是,如果传入编码或错误参数,则行为会有所不同。

  

如果给出编码和/或错误,unicode()将解码对象   它可以是8位字符串,也可以是使用的字符缓冲区   用于编码的编解码器。 encoding参数是一个给出名称的字符串   编码;如果编码未知,则引发LookupError。   错误处理是根据错误完成的;这指定了   处理输入编码中无效的字符。如果   错误是'严格'(默认值),错误会引发ValueError,   而'ignore'的值会导致错误被忽略,而a   'replace'的值导致官方的Unicode替换字符,   U + FFFD,用于替换不能输入的字符   解码。另请参阅编解码器模块。

     

如果没有给出可选参数,unicode()将模仿   str()的行为,除了它返回Unicode字符串而不是   8位字符串。更准确地说,如果object是Unicode字符串或   子类它将返回该Unicode字符串而无需任何额外的   解码应用。

您无法将u''转换为unicode的原因是因为它已经是unicode表示。当Python尝试使用ascii编解码器(默认编解码器,因为你没有指定一个)解码它时,它意识到该字符串已经是Unicode,并抛出一个错误(“Python:Oi你为什么要尝试转换unicode串到unicode?“)

如果没有指定错误参数,正如您在文档中看到的那样,Python可以将unicode字符串转换为unicode。如果它已经是unicode,它将返回unicode字符串而不需要任何额外的解码。

standard link让人们了解unicode是什么。

如果您确实希望能够执行此操作(例如,如果您想编写接受常规字符串和unicode字符串的代码),则在将字符串转换回Unicode之前对其进行编码。

示例:

>>> unicode(u''.encode('ascii', errors='replace'))

如果您想使用其他编码(ascii是默认编码):

>>> unicode(u''.encode('utf-8', errors='replace'), 'utf-8')

答案 1 :(得分:0)

我认为unicode()函数应该采用string类型的数据,而不是unicode类型的数据:

unicode()构造函数具有签名unicode(string [,encoding,errors])。它的所有参数都应该是8位字符串。第一个参数使用指定的编码转换为Unicode; 如果您不使用编码参数,则使用ASCII编码进行转换,因此大于127的字符将被视为错误:

>>> unicode('abcdef')
u'abcdef'
>>> s = unicode('abcdef')
>>> type(s)
<type 'unicode'>
>>> unicode('abcdef' + chr(255))    
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
ordinal not in range(128)

u''正在编码空字符串(我认为它不是大于127的字符)。没有编码参数应该没问题,但我相信unicode会引发错误,因为它不应该定期接受Unicode。

我现在正在尽力猜测这一点,所以任何更正都会受到赞赏。