Python:从ISO-8859-1 / latin1转换为UTF-8
我已经使用email模块从Quoted-printable到ISO-8859-1解码了这个string。 这给了我像“\ xC4pple”,这将对应于“Äpple”(苹果在瑞典语)string。 但是,我不能将这些string转换为UTF-8。
>>> apple = "\xC4pple" >>> apple '\xc4pple' >>> apple.encode("UTF-8") Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 0: ordinal not in range(128)
我该怎么办?
尝试先解码,然后编码:
apple.decode('iso-8859-1').encode('utf8')
这是一个常见的问题,所以这里有一个比较彻底的例子。
对于非Unicodestring(即没有像u'\xc4pple'
那样的前缀),必须从本地编码( iso8859-1
/ latin1
,除非用神秘的sys.setdefaultencoding
函数修改 )解码为unicode
,然后编码为字符集,可以显示你想要的字符,在这种情况下,我build议UTF-8
。
首先,这里有一个方便的实用函数,它将帮助阐明Python 2.7string和unicode的模式:
>>> def tell_me_about(s): return (type(s), s)
一个纯string
>>> v = "\xC4pple" # iso-8859-1 aka latin1 encoded string >>> tell_me_about(v) (<type 'str'>, '\xc4pple') >>> v '\xc4pple' # representation in memory >>> print v ?pple # map the iso-8859-1 in-memory to iso-8859-1 chars # note that '\xc4' has no representation in iso-8859-1, # so is printed as "?".
解码一个iso8859-1string – 将纯string转换为unicode
>>> uv = v.decode("iso-8859-1") >>> uv u'\xc4pple' # decoding iso-8859-1 becomes unicode, in memory >>> tell_me_about(uv) (<type 'unicode'>, u'\xc4pple') >>> print v.decode("iso-8859-1") Äpple # convert unicode to the default character set # (utf-8, based on sys.stdout.encoding) >>> v.decode('iso-8859-1') == u'\xc4pple' True # one could have just used a unicode representation # from the start
多一点插图 – 用“Ä”
>>> u"Ä" == u"\xc4" True # the native unicode char and escaped versions are the same >>> "Ä" == u"\xc4" False # the native unicode char is '\xc3\x84' in latin1 >>> "Ä".decode('utf8') == u"\xc4" True # one can decode the string to get unicode >>> "Ä" == "\xc4" False # the native character and the escaped string are # of course not equal ('\xc3\x84' != '\xc4').
编码为UTF
>>> u8 = v.decode("iso-8859-1").encode("utf-8") >>> u8 '\xc3\x84pple' # convert iso-8859-1 to unicode to utf-8 >>> tell_me_about(u8) (<type 'str'>, '\xc3\x84pple') >>> u16 = v.decode('iso-8859-1').encode('utf-16') >>> tell_me_about(u16) (<type 'str'>, '\xff\xfe\xc4\x00p\x00p\x00l\x00e\x00') >>> tell_me_about(u8.decode('utf8')) (<type 'unicode'>, u'\xc4pple') >>> tell_me_about(u16.decode('utf16')) (<type 'unicode'>, u'\xc4pple')
unicode与UTF和latin1的关系
>>> print u8 Äpple # printing utf-8 - because of the encoding we now know # how to print the characters >>> print u8.decode('utf-8') # printing unicode Äpple >>> print u16 # printing 'bytes' of u16 pple >>> print u16.decode('utf16') Äpple # printing unicode >>> v == u8 False # v is a iso8859-1 string; u8 is a utf-8 string >>> v.decode('iso8859-1') == u8 False # v.decode(...) returns unicode >>> u8.decode('utf-8') == v.decode('latin1') == u16.decode('utf-16') True # all decode to the same unicode memory representation # (latin1 is iso-8859-1)
Unicodeexception
>>> u8.encode('iso8859-1') Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128) >>> u16.encode('iso8859-1') Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0: ordinal not in range(128) >>> v.encode('iso8859-1') Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 0: ordinal not in range(128)
通过从特定编码(latin-1,utf8,utf16)转换为unicode(例如u8.decode('utf8').encode('latin1')
。
所以也许可以得出以下原则和概括:
- 一个
str
types是一组字节,可能有一些编码,如Latin-1,UTF-8和UTF-16 - 一个
unicode
types是一组字节,可以转换为任意数量的编码,最常用的是UTF-8和latin-1(iso8859-1) -
print
命令有自己的编码逻辑 ,设置为sys.stdout.encoding
并默认为UTF-8 - 在转换为另一种编码之前,必须将一个
str
解码为unicode。
当然,所有这些在Python 3.x中都有所改变。
希望是照亮。
进一步阅读
- 人物与Bytes ,Tim Bray。
Armin Ronacher的非常说明性的咆哮:
- Python的Unicode更新指南(2013年7月2日)
- Python 2和3中关于Unicode的更多信息(2014年1月5日)
- UCS与UTF-8作为内部string编码(2014年1月9日)
- Python 3中的所有你不想知道的Unicode(2014年5月12日)
解码为Unicode,将结果编码为UTF8。
apple.decode( 'latin1的')。编码( 'UTF8')
对于Python 3:
bytes(apple,'iso-8859-1').decode('utf-8')
我用这个文本错误地编码为iso-8859-1(显示像VeÅ\ xembe? )而不是utf-8。 此代码生成正确的版本Veřejné 。
concept ='concept'('ascii','ignore')concept = MySQLdb.escape_string(concept.decode('latin1')。encode('utf8')。rstrip())
我这样做,我不知道这是一个好方法,但它每次都有效!