5

python3 中的编码和解码

 3 years ago
source link: https://windard.com/blog/2017/05/14/Python-Encode-And-Decode
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

python3 中的编码和解码

2017-05-14

在 Python 2 中的 str 和 Unicode 傻傻分不清,如果还不幸在 Windows 平台下,那简直是一场灾难。在 Python 3 中这种情况大为好转, str 默认是 Unicode 编码,但是又出现了另一个问题。在 Python 2 中 bytes 和 str 是隐式相同的,在 Python 3 中它们被严格区分开。

世界上最幸福的 Python 程序员是在 Mac 上写 Python 3 ,最不幸的 Python 程序员是在 Windows 下写 Python 2。

为了更好的与 Python 2 的对比,本文在 Ubuntu 下进行,字符串都是指中文字符串。

bytes/str

字节流和字符串,前者表示二进制数据,后者表示文本,在 Python 3 中所有的网络协议中使用的都是 bytes 。

在 Python 2 中这两者是可以混用的,但是在 Python 3 中则不能,这表示你不能拼接 bytes 和 str ,不能在 bytes 中查找 str, 不能在 str 中查找 bytes。

bytes 和 str 的联系是 bytes 解码(decode)为 str, str 编码(encode)为 bytes。

所以 bytes 只有 decode 函数,而无 encode 函数,str 只有 encode 函数,而无 decode 函数。

因为在 Python 3 中所有的字符串都是 Unicode 格式,采用 utf-8 编码,所以默认的编码和解码都是默认采用 utf-8 格式。

python3

str/unicode

不要忘了 Python 2 中文编码带来的恐怖。

字符串和万国码,在 Python 3 中这两者是一致的,但是在 Python 2 中,因为 Python 2 的推出比万国码的推出更早,所以在 Python 2 中这两者是不同的。

不过在 Python 2 中字符串和字节流是相同的。

在 Python 2 中字符串和万国码不能混用,这表示不能拼接 Unicode 和 str,不能在 Unicode 中查找 str,不能在 str 中查找 Unicode。

Unicode 和 str 的联系是 Unicode 编码(encode)为 str, str 解码(decode)为 Unicode。

所以 Unicode 编码为 str 之后不能再次编码,str 解码为 Unicode 之后,不能再次解码。

python2

在 Python 2 中没有默认的解码和编码方式,故解码和编码都要声明是 utf-8。

unicode/gbk

虽然不想说,但是还是要面对,目前市场份额最大的 Windows 。

Windows 的中文默认编码为 gbk,虽然它有很多名字 gb2312,gbk,chap 936,但这些都是一路货色,不与 Unicode 相同。

Python 2 中的除 ASCII 之外字符,采用与本机编码相同的编码格式,所以在 Windows 下就是采用 gbk 编码。

字符串默认采用 gbk 编码,所以在 Windows 下的话,字符串其实 gbk 字符串,在与 Unicode 字符串的转换中就更多了一步。

windows

utf-8/gbk

在 Python 3 中,已经不论是在什么平台下都是采用 Unicode 编码格式,可以编码为 bytes 格式,然后解码,也可以编码为 gbk 格式,然后解码。这才是正确的方式。

utf-8 与 gbk 是同一等级的,两者只是不同的编码方式,utf-8 中将每个字符串编码为 3 个字节,而 gbk 中将每个字符串编码为 2 个字节。

Unicode 与 ASCII 与 gbk 也是同一个等级的,三者是对不同的文字有不同的表示,ASCII 中每个文字一个字节,才能表示西文字母和数字等,不能表示中文,gbk 中每个文字两个字节,可以表示汉字,Unicode 中每个文字一个 Unicode 单位,字节数的话由编码方式来决定,utf-8 是变长的编码方式,中文是三个字节长,范围在 \u4e00-\u9fa5 之间。

perfect

在 Python 2 中,字符串和字节流是相亲相爱的一家人,Unicode 是标准,字符串转化为 Unicode 需要解码,Unicode 转换为字符串需要编码。

在 Python 3 中,字符串和 Unicode 是一家人,而且还是标准,字节流转换为字符串需要解码,字符串转化为字节流需要编码。

在写入到文件中时,除非使用二进制格式打开,否则都是只能写入字符串,所以在 Python 2 中由 Unicode 编码为字符串,在 Python 3 中由字节流解码为字符串 (Unicode) 。

在网络文件接收到的数据,一般都是采用 Unicode 格式编辑,在 Python 2 中可以由字符串解码为 Unicode ,在 Python 3 中可以由字节流解码为 Unicode (字符串)。

Unicode 二三事

在 python2 中的 Unicode 是类似于 u"\uxxxx" , 但是其实这只能表示 \u0000-\uFFFF 的 Unicode 编码,而实际上 Unicode 编码不只是这些内容,如果有更大的 Unicode ,比如说 emoji 😊 . 那就需要通过 u"\Uxxxxxxxx" 来表示, 使用大U 可以表示 \U00010000-\UFFFFFFFF 的 Unicode 编码, 即 小u 表示 2byte 16bit 的字符,大U 表示 4byte 32 bit 的字符。

>>> a  = u'😊'
>>> a
u'\U0001f60a'
>>> print u'\U0001f60a'
😊
>>> print u'\u0001f60a'
f60a

Unicode 中文的编码范围在 \u4E00-\u9FA5, 但是常用的是包含中日韩各种表意文字范围 \u2E80-\uFE4F

汉字 Unicode 编码范围

Unicode中文和特殊字符的编码范围

Unicode 格式是 u"\uxxxxxx",如果编码为 utf-8 或者 gbk ,使用 decode 即可转换为 Unicode ,但是有时候会遇到 "\uxxxx" 形式的字符串,如果再次进行解码则会变成 u"\\uxxxx", 这个时候则需要使用 decode("unicode-escape") ,才能够变成正常的 Unicode 字符。

或者非常恶心的方式使用 eval("u\"" + "\uxxxx" + "\"") 得到 u"\uxxxx"


本文固定链接:https://windard.com/blog/2017/05/14/Python-Encode-And-Decode
原创文章,转载请注明出处:python3 中的编码和解码 By Windard


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK