字符串编码和解码?

wai*_*ani 53 python python-2.7

以下是我对错误消息的尝试.我究竟做错了什么?

string.decode("ascii", "ignore")
Run Code Online (Sandbox Code Playgroud)

__CODE__

string.encode('utf-8', "ignore")
Run Code Online (Sandbox Code Playgroud)

__CODE__

Ign*_*ams 87

你不能解码unicode,你不能编码str.试着做它周围的其他方法.

  • 准确但可能有点电报,所以我添加了更详细的解释. (8认同)
  • 我是唯一一个认为Python有这种错误方法的人吗?当我把一个python字符串变成它的二进制utf-8表示时,肯定应该被称为"编码",而不是相反? (8认同)

Dun*_*can 61

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

在第一个示例中string是类型unicode,您尝试解码它,这是一个将字节字符串转换 unicode的操作.Python的有益尝试将Unicode值转换为str使用默认的"ASCII"编码,但因为你的字符串包含非ASCII字符,你得到了它说,蟒蛇无法错误编码一个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)
Run Code Online (Sandbox Code Playgroud)

在第二种情况下,您反向尝试编码字节字符串.编码是一种将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)
Run Code Online (Sandbox Code Playgroud)


jpm*_*c26 27

除了获取decodeencode反向,我认为这里的部分答案实际上是不使用ascii编码.这可能不是你想要的.

首先,想想str你会是一个纯文本文件.它只是一堆字节,没有实际附加的编码.如何解释它取决于阅读它的任何代码片段.如果您不知道本段所讨论的内容,请在进一步了解之前,先阅读Joel的绝对最低每个软件开发人员,正确必须知道Unicode和字符集.

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

问题是,在实践中,你遇到了两者.有些图书馆给你一个str,有些图书馆给你一个str.当你流式传输一系列字节时(例如从磁盘到磁盘或通过Web请求),这是有意义的.所以你需要能够来回翻译.

输入codecs:它是这两种数据类型之间的转换库.您可以使用从文本字符串()encode生成一系列bytes(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"
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?我给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"
Run Code Online (Sandbox Code Playgroud)

我给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'
Run Code Online (Sandbox Code Playgroud)

('\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
    
    Run Code Online (Sandbox Code Playgroud)
  • 或者也许你正试图在某处写出来.目的地期望的编码是什么?用它来把它翻译成一个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]
    
    Run Code Online (Sandbox Code Playgroud)
  • 您是否只是为了互操作性而在内存中来回翻译?然后选择一个编码并坚持下去; 'utf-8'可能是最好的选择:

    u = u'My string'
    s = codecs.encode(u, 'utf-8')
    newu = codecs.decode(s, 'utf-8')
    
    Run Code Online (Sandbox Code Playgroud)

在现代编程中,您可能永远不会想要使用'ascii'任何编码.它是所有可能字符的极小子集,我所知道的系统默认使用它或任何其他字符.

Python 3尽最大努力通过更改名称来使这一点变得非常清晰.在Python 3中,str被替换为bytes,unicode并被替换为str.