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')

所以也许可以得出以下原则和概括:

  • 一个strtypes是一组字节,可能有一些编码,如Latin-1,UTF-8和UTF-16
  • 一个unicodetypes是一组字节,可以转换为任意数量的编码,最常用的是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())

我这样做,我不知道这是一个好方法,但它每次都有效!