以下是我的尝试及错误信息,请问我做错了什么?
string.decode("ascii", "ignore")
UnicodeEncodeError: 'ascii'编解码器无法将字符u'\xa0'编码到位置37:序数不在范围内(128)。string.encode('utf-8', "ignore")
UnicodeDecodeError: 'ascii'编解码器无法解码位置为37的0xc2字节:该序数不在128的范围内。以下是我的尝试及错误信息,请问我做错了什么?
string.decode("ascii", "ignore")
UnicodeEncodeError: 'ascii'编解码器无法将字符u'\xa0'编码到位置37:序数不在范围内(128)。string.encode('utf-8', "ignore")
UnicodeDecodeError: 'ascii'编解码器无法解码位置为37的0xc2字节:该序数不在128的范围内。你不能解码一个 unicode
,也不能编码一个 str
。试着反过来做 就可以了。
不知道原问题中省略了什么,但是假设使用的是Python2.x,关键是要仔细阅读错误信息:特别是当你调用“encode”而消息显示“decode”,或者反之,还有包含在消息中的值的类型。
在第一个例子中,“string”的类型是“unicode”,而您尝试对其进行解码操作,这是将字节字符串转换为Unicode的操作。 Python会尝试使用默认的“ascii”编码将Unicode值转换为“str”,但由于您的字符串包含非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)
>>> "\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
从文本字符串 (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提供了一系列字节,然后告诉它:“在假定这串字节是使用'utf-8'
编码的前提下,给我它们的unicode
版本。” 它按照我的要求做了,那些字节(一个心形字符)现在被视为一个整体,并用它们的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"编码将该字符串转换为字节序列。 Python完成了这个任务,但现在的心形符号只是一堆无法作为ASCII字符打印出来的字节,所以Python显示了十六进制。
当然,我们也可以使用其他编码方式:
>>> 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
使用的编码方式。
它是来自文件?来自 Web 请求?来自数据库?然后源确定编码方式。找出源的编码方式,并使用该编码方式将其转换为 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
。
x.decode(some_encoding).encode(some_encoding) == x
是否为真?(使用py3符号而不是codecs,type(x) == bytes
) - Mr_and_Mrs_D这是因为您的输入字符串无法根据编码规则进行转换(默认情况下是严格的)。
我不知道,但我总是直接使用unicode()构造函数进行编码,至少在官方文档中是这样的:
unicode(your_str, errors="ignore")
unicode("\xe2\x9d\xa4", errors='ignore')
会得到u''
.) 如果这是可以接受的结果,那么这可能是可以的。虽然在大多数情况下丢失数据都不可接受,但至少此答案需要详细说明这样做的适当性。 - jpmc26
string
的值是什么?它是什么类型? - Marco de Wit