字符串编码和解码?

2024-05-29 04:07:06 发布

您现在位置:Python中文网/ 问答频道 /正文

以下是我的错误消息尝试。我做错什么了?

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)


Tags: in消息string错误asciinotpositionrange
3条回答

你不能解码一个unicode,也不能编码一个str。试着去做the other way around

猜测原始问题中遗漏的所有内容,但是,假设Python 2.x,关键是仔细阅读错误消息:特别是在调用“encode”但消息显示“decode”的情况下,反之亦然,还包括消息中包含的值的类型。

在第一个示例中,stringunicode类型,您试图对其进行解码,这是一个将字节字符串转换为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想象成一个纯文本文件。它只是一堆字节,实际上没有附加任何编码。它的解释取决于读它的代码。如果你不知道这一段是在说什么,在你进一步阅读之前,现在就去读乔尔的The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets

当然,我们都知道造成的混乱。答案是,至少在内存中,所有字符串都有一个标准编码。这就是unicode进来的地方。我很难准确地追踪Python在内部使用的编码,但这并不重要。关键是你知道它是一个字节序列,以某种方式被解释。所以你只需要考虑字符本身,而不是字节。

问题是在实践中,两者都会遇到。有些库会给你一个str,有些库会给你一个str。当然,当您在流式传输一系列字节(例如磁盘或从磁盘或通过web请求)时,这是有意义的。所以你需要能够前后翻译。

输入codecs:这是这两种数据类型之间的转换库。使用encode从文本字符串(unicode)生成字节序列(str),使用decode从字节序列(str)获取文本字符串(unicode)。

例如:

>>> 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'中。”它按照我的要求做了,这些字节(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和拉丁语-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

相关问题 更多 >

    热门问题