繁体   English   中英

字符串编码和解码?

[英]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)

除了获得向后decodeencode之外,我认为这里的部分答案实际上是不使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM