一个简单的例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import traceback
e_u = u'abc'
c_u = u'中国'
print sys.getdefaultencoding()
try:
print e_u.decode('utf-8')
print c_u.decode('utf-8')
except Exception as e:
print traceback.format_exc()
reload(sys)
sys.setdefaultencoding('utf-8')
print sys.getdefaultencoding()
try:
print e_u.decode('utf-8')
print c_u.decode('utf-8')
except Exception as e:
print traceback.format_exc()
输出:
ascii
abc
Traceback (most recent call last):
File "test_codec.py", line 15, in <module>
print c_u.decode('utf-8')
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
utf-8
abc
中国
有些问题困扰我几天,当我想彻底了解python中的编解码器时,我想确定我认为是对的:
在ascii
默认编码下,u'abc'.decode('utf-8')
没有错误,但u'中国'.decode('utf-8')
有错误。
我认为什么时候u'中国'.decode('utf-8')
,Python检查并发现u'中国'
是unicode,所以它尝试u'中国'.encode(sys.getdefaultencoding())
,这会导致问题,例外是UnicodeEncodeError
,解码时不会出错。
但u'abc'
与'abc'
(&lt; 128)具有相同的代码点,因此没有错误。
在Python 2.x中,python内部存储变量值如何?如果字符串中的所有字符都是&lt; 128,视为ascii
,如果&gt; 128,视为utf-8
?
In [4]: chardet.detect('abc')
Out[4]: {'confidence': 1.0, 'encoding': 'ascii'}
In [5]: chardet.detect('abc中国')
Out[5]: {'confidence': 0.7525, 'encoding': 'utf-8'}
In [6]: chardet.detect('中国')
Out[6]: {'confidence': 0.7525, 'encoding': 'utf-8'}
答案 0 :(得分:1)
简短回答
您必须使用encode()
,否则请将其删除。不要将decode()
与unicode字符串一起使用,这没有任何意义。此外,sys.getdefaultencoding()
无论如何也无法提供帮助。
长答案,第1部分:如何正确完成?
如果你定义:
c_u = u'中国'
然后c_u
已经是一个unicode字符串,也就是说,它已经使用你的-*- coding: utf-8 -*-
声明由Python解释器从字节字符串(源文件)解码为unicode字符串。
如果您执行:
print c_u.encode()
您的字符串将被编码回UTF-8,并且该字节字符串将被发送到标准输出。请注意,这通常会自动发生,因此您可以将其简化为:
print c_u
答案很长,第2部分:c_u.decode()有什么问题?
如果执行c_u.decode()
,Python将
请注意,如果您的对象首先是一个unicode字符串,那么这没有任何意义 - 您只需将其转换回来。但为什么会失败呢?嗯,这是Python的一个奇怪功能,第一步(1.),即从unicode字符串到字节字符串的任何隐式转换,通常使用sys.getdefaultencoding(),而sys.getdefaultencoding()依次默认为ASCII字符集。换句话说,
c_u.decode()
大致翻译为:
c_u.encode(sys.getdefaultencoding()).decode()
这就是它失败的原因。
请注意,虽然您可能想要更改默认编码,但请不要忘记其他第三方库可能包含类似问题,如果默认编码与ASCII不同,可能会中断。
话虽如此,我坚信如果Python首先没有定义unicode.decode()
会更好。 Unicode字符串已经被解码,再次解码它们没有意义,特别是以Python的方式。