[英]string encoding and decoding?
这是我尝试的错误消息。 我究竟做错了什么?
string.decode("ascii", "ignore")
UnicodeEncodeError:'ascii'编解码器无法在位置37编码字符u'\\ xa0':序数不在范围内(128)
string.encode('utf-8', "ignore")
UnicodeDecodeError:'ascii'编解码器无法解码位置37的字节0xc2:序数不在范围内(128)
您无法解码unicode
,也无法编码str
。 尝试以另一种方式进行操作 。
猜测所有原始问题中遗漏的内容,但是假设使用Python 2.x,关键是要仔细阅读错误消息:特别是在您调用“ encode”但消息显示为“ decode”(反之亦然)的情况下,消息中包含的值的类型。
在第一个示例中, 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)
除了获得向后decode
和encode
之外,我认为这里的部分答案实际上是不使用ascii
编码 。 这可能不是您想要的。
首先,请像对待纯文本文件一样考虑str
。 它只是一束字节,实际上没有附加任何编码。 它的解释方式取决于所读取的任何代码。 如果您不了解本段的内容,请在继续之前阅读Joel的“绝对最低限度的软件开发人员绝对知识,绝对必须肯定地了解Unicode和字符集” 。
自然,我们都知道造成的混乱。 答案是至少在内存中具有针对所有字符串的标准编码。 那就是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一个字节序列,然后我告诉它:“给我这个的unicode
版本,因为这个字节序列位于'utf-8'
。” 正如我所问的那样,这些字节( 心脏字符 )现在被视为一个整体,由其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'
是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
。
这是因为您的输入字符串无法根据编码规则进行转换(默认情况下为严格限制)。
我不知道,但是我总是直接使用unicode()构造函数进行编码,至少这是官方文档中的方法 :
unicode(your_str, errors="ignore")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.