以下是我对错误消息的尝试。我做错了什么?
string.decode("ascii", "ignore")
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 37: ordinal not in range(128)
string.encode('utf-8', "ignore")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 37: ordinal not in range(128)
答案 0 :(得分:85)
您无法解码unicode
,也无法对str
进行编码。尝试做the other way around。
答案 1 :(得分:61)
猜测原始问题中遗漏的所有内容,但是,假设Python 2.x,关键是要仔细阅读错误消息:特别是在您调用'编码'但消息说'解码'反之亦然,但也包括消息中包含的值的类型。
在第一个示例中,string
的类型为unicode
,并且您尝试对其进行解码,这是将字节字符串转换为 unicode的操作。 Python帮助尝试使用默认的' ascii'将unicode值转换为str
。编码,但由于你的字符串包含一个非ascii字符,你得到的错误表明Python无法编码一个 unicode 值。这是一个显示输入字符串类型的示例:
>>> u"\xa0".decode("ascii", "ignore")
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
u"\xa0".decode("ascii", "ignore")
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 0: ordinal not in range(128)
在第二种情况下,您反向尝试编码字节字符串。编码是一种将unicode转换为字节字符串的操作,因此Python首先尝试将字节字符串转换为unicode,因为你没有给它一个ascii字符串,所以默认的ascii解码器失败了:
>>> "\xc2".encode("ascii", "ignore")
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
"\xc2".encode("ascii", "ignore")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 0: ordinal not in range(128)
答案 2 :(得分:27)
除了向后收取decode
和encode
之外,我认为这里的部分答案实际上是不使用ascii
编码。它可能不是你想要的。
首先,将str
视为纯文本文件。它只是一堆没有实际附加编码的字节。如何解释它取决于阅读它的任何代码片段。如果你不知道这段话正在讨论什么,那么在你再继续之前,请立即阅读Joel的The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets。
当然,我们都知道造成的混乱。答案是,至少在内存中,对所有字符串都有标准编码。这就是unicode
进来的地方。我无法确切地追踪Python内部使用的编码,但这并不重要。关键是你知道它是以某种方式解释的字节序列。所以你只需要考虑字符本身,而不是字节。
问题在于,在实践中,你遇到了两者。有些图书馆会为您提供str
,有些图书馆会提供str
。当然,无论何时流式传输一系列字节(例如从磁盘传输或从磁盘请求传输),这都是有意义的。所以你需要能够来回翻译。
输入codecs
:它是这两种数据类型之间的翻译库。您使用encode
从文本字符串(str
)生成字节序列(unicode
),然后使用decode
获取文本字符串(unicode
})来自字节序列(str
)。
例如:
>>> s = "I look like a string, but I'm actually a sequence of bytes. \xe2\x9d\xa4"
>>> codecs.decode(s, 'utf-8')
u"I look like a string, but I'm actually a sequence of bytes. \u2764"
这里发生了什么?我给Python一个字节序列,然后我告诉它,&#34;给我这个unicode
版本,因为这个字节序列在'utf-8'
。&#34;它就像我问的那样,这些字节(a heart character)现在被视为一个整体,由它们的Unicode代码点表示。
让我们走另一条路:
>>> u = u"I'm a string! Really! \u2764"
>>> codecs.encode(u, 'utf-8')
"I'm a string! Really! \xe2\x9d\xa4"
我给Python一个Unicode字符串,我要求它使用'utf-8'
编码将字符串转换为字节序列。所以它确实如此,现在心脏只是一堆字节,它不能打印成ASCII;所以它显示了十六进制。
当然,我们也可以使用其他编码:
>>> s = "I have a section \xa7"
>>> codecs.decode(s, 'latin1')
u'I have a section \xa7'
>>> codecs.decode(s, 'latin1')[-1] == u'\u00A7'
True
>>> u = u"I have a section \u00a7"
>>> u
u'I have a section \xa7'
>>> codecs.encode(u, 'latin1')
'I have a section \xa7'
('\xa7'
是两者中的section character
Unicode和Latin-1。)
因此,对于您的问题,您首先需要确定str
的编码方式。
它来自文件吗?来自网络请求?从你的数据库?然后源确定编码。找出源代码的编码并使用它来将其转换为unicode
。
s = [get from external source]
u = codecs.decode(s, 'utf-8') # Replace utf-8 with the actual input encoding
或者您可能正试图在某处写出来。目的地期望的编码是什么?用它将其翻译成str
。 UTF-8是纯文本文档的不错选择;大多数事情都可以阅读。
u = u'My string'
s = codecs.encode(u, 'utf-8') # Replace utf-8 with the actual output encoding
[Write s out somewhere]
您是否只是为了互操作性而在内存中来回翻译?然后选择一个编码并坚持下去; 'utf-8'
可能是最佳选择:
u = u'My string'
s = codecs.encode(u, 'utf-8')
newu = codecs.decode(s, 'utf-8')
在现代编程中,您可能永远不会想要使用'ascii'
编码。它是所有可能字符的极小子集,我知道没有任何系统默认使用它或任何东西。
Python 3尽最大努力通过更改名称来使这个非常更清晰。在Python 3中,str
已替换为bytes
,unicode
已替换为str
。
答案 3 :(得分:2)
这是因为您的输入字符串无法根据编码规则进行转换(默认情况下为strict)。
我不知道,但我总是使用直接使用unicode()构造函数进行编码,至少这是official documentation的方式:
unicode(your_str, errors="ignore")