在Python中,u''前缀和unicode()有什么区别?

10
< p >"u''"前缀和unicode()有什么区别?< /p >
# -*- coding: utf-8 -*-
print u'上午'  # this works
print unicode('上午', errors='ignore') # this works but print out nothing
print unicode('上午') # error

第三个print出现错误:UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0

如果我有一个包含非ASCII字符的文本文件,比如“上午”,该如何正确读取并打印出来?


https://dev59.com/8nRA5IYBdhLWcg3w_C4w - Praveen
你在编辑中添加的问题有点荒谬。你的 "\x97" 字节的编码是什么?无论你的答案是什么,都要将其用作 unicode(或 str.decode)的参数,而不是 "utf-8"。正如 Joel Spolsky 在 Martijn Pieters 链接的帖子 中所写:“没有知道使用哪种编码的字符串是没有意义的。 - Blckknght
4个回答

16
  • u'..'是一个字符串字面量,它会根据源编码声明解码字符。

  • unicode()是一个将其他类型转换为unicode对象的函数,您给它提供了一个字节字符串字面量。它将根据默认 ASCII 编解码一个字节串。

因此,您创建了一个使用不同类型的字面符号的字节字符串对象,然后尝试将其转换为unicode()对象,但失败了,因为str -> unicode 转换的默认编解码器是 ASCII。

这两者是非常不同的。如果想使用后者,需要给它一个显式编解码器:

print unicode('上午', 'utf8')

这两者的关系类似于使用 0xFFint('0xFF', 0) 的方式;前者使用十六进制表示定义了数值为255的整数,而后者使用 int() 函数从字符串中提取整数。

另一种方法是使用 str.decode() 方法

print '上午'.decode('utf8')

除非您知道自己在做什么,否则不要尝试使用错误处理程序(例如'ignore''replace')。特别是'ignore'可能掩盖了选择错误编解码器时的潜在问题。

您可能想了解有关Python和Unicode的更多信息:


谢谢。它有效。但是,我尝试读取一个包含非ASCII字符的文本文件,例如“上午”。对于文件的每一行,我执行unicode(line,'utf8'),它显示与问题描述中所说的相同的错误。 - DehengYe
1
@DehengYe:也许你的文件使用了不同的编解码器?而且不要使用unicode()来解码每一行。你可以使用import io,然后使用io.open(filename, encoding='utf8')(或其他编解码器)来让Python在读取时为你解码文件内容。 - Martijn Pieters
我遇到了新问题。你能看到我的新编辑吗?谢谢。@MartijnPieters - DehengYe
@DehengYe:请不要在当前帖子中提出新问题,而是使用新的帖子来提问。你不能转换那个字节,因为它不是UTF-8编码。你有不同的编解码器,你需要弄清楚你拥有的数据是什么。不要尝试将其解码为UTF-8。 - Martijn Pieters

2
在Python 2.7.x中,如果一个str没有以u''为前缀,解释器看到的是一个字节字符串,没有明确的编码。当执行unicode()时,如果您不告诉解释器如何处理这些字节,它(就像你看到的那样)将默认尝试通过ascii编码方案来decode这些字节。这是将普通的str转换为unicode对象的预备步骤。使用ascii进行decode意味着:尝试使用硬编码映射解释str的每个字节,映射值在0和127之间。您遇到的错误类似于dict KeyError:解释器遇到了一个字节,ascii编码方案没有指定映射。由于解释器不知道该怎么处理这个字节,所以会抛出一个错误。您可以通过告诉解释器使用另一组编码/解码映射来decode字节,从而更改这个预备步骤,例如超越ascii的UTF-8,如其他答案所述。如果解释器在所选方案中为str中的每个字节(或字节)找到一个映射,它将成功解码,并使用生成的映射来产生一个unicode对象。Python的unicode对象是一系列Unicodecode points。Unicode代码空间中有1,112,064个有效代码点。如果您选择的解码方案与您的文本(或代码点)编码的方案相同,则打印输出应与原始文本相同。也可以考虑尝试Python 3。相关差异在下面的第一条评论中有解释。

1
Python 3不会默认将字符串转换为utf-8编码 - 相反,str是Unicode文本(一系列Unicode代码点),就像2.x中的unicode类型。如果您没有使用编码声明,Python 3中的默认UTF8是指源文件编码(在Python 3之前是ASCII,在2.5之前是ISO 8859-1)。 - lvc

0

Unicode是一种对象类型,而'u'是用于表示该对象为Unicode对象的文字。它类似于用于表示长整型的'L'文字。


如果您的字面值大于sys.maxint,则不需要使用L前缀来创建长整型,而且long(123)也不会产生可以通过额外参数进行调节的翻译步骤。 - Martijn Pieters
此外,除了索引操作和某些 C 调用之外,长整型和普通整型几乎是完全相同的东西。 - Martijn Pieters

0
请尝试:'上午'.decode('utf8','ignore').encode('utf8')

我尝试了一下,在读取非ASCII代码的文件时,这确实有效。所以我点了个赞。 - DehengYe
为什么需要额外的编码?当然,'byte str literal'.decode('source codec')unicode('byte str literal', 'source codec') 执行的是相同的操作。 - Martijn Pieters
@DehengYe:这是因为'ignore'错误处理程序会使任何输入都能正常工作。这并不意味着你得到了可用的文本。 - Martijn Pieters
1
为什么要使用“忽略”?这只是掩盖了任何问题,如果输入实际上不是UTF-8呢? - Martijn Pieters
@DehengYe:假设你的输入文件使用GBK编码,那么使用line.decode('utf8', 'ignore')会给你一个结果,但它不会是任何有用的结果。u'上午'.encode('gbk').decode('utf8', 'ignore')会给你一个空字符串,因为编码后的字符串中的所有字节都不是有效的UTF-8字节,所以在解码时都被忽略了。但GBK是用于中文文本的最常见编码之一。 - Martijn Pieters
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接