Python 编码在现在 Python3 比较普及的情况下应该不是什么头疼的问题了,但感觉搞清楚它还是比较有意义的。我在读了雨痕的《 Python 学习笔记》中的相关内容以后,感觉对于编码的理解比以前加深了一些,所以写出来和大家分享一下,还请大家多多指正。
1
imn1 2016-11-09 12:51:02 +08:00
写程序一律不应该写 gb2312 ,而应该写 gbk 或 cp936 ,两者的字符数量不是一个等级的
& python 中的 ASCII 编码也不包含高位字节,只是 0-127 的字符,处理包含高位字节应该用 latin-1 编码 文章中的提及的都不是太难处理的问题,不熟悉编码的人,可能处理数据库读写时的不同编码更棘手 另外,处理手动输入或赋值的字符编码也不难,因为基本都在程序环境内,但从外部读入的就会麻烦了 例如 外部传入字符串"\u2665", python 自然就变成 \\u2665 ,而不是 u'\u2665',处理方式就变了,已经不是编码问题,而是变成字符串转换问题 |
2
Sylv 2016-11-09 13:03:31 +08:00 via iPhone
魔幻三行其实一直不是正确的编码问题解决方法,建议别写进文章里,以免误导后人。
|
3
Yinz 2016-11-09 13:13:50 +08:00
『 Python3 中正式将这两个概念区分开了, Str 表示的是字符串,拥有编码类型, Bytes 表示的是字节流,没有编码类型。』
这句与我的理解相反? str 是 unicode ,无编码类型; bytes 是字节流,有编码类型,如 utf-8 |
4
Sylv 2016-11-09 13:36:49 +08:00
看了文章,感觉你对 Python 的编码理解还是有点乱,特别是文中指定编码和实际编码的部分没说清楚。
|
6
Sylv 2016-11-09 19:40:11 +08:00
@dousao 呃,之前读了一遍觉得有的地方有点乱,不知该从哪说起。
我又看了遍文章,指出一些我和作者理解不同的地方。 1. 「 Str 表示的是字符串,拥有编码类型, Bytes 表示的是字节流,没有编码类型。」 这句话三楼也指出问题了: Python 3 中的 str 字符串是 Unicode ,存储的是 code points (码点),是没有编码的;而 bytes 相当于 Python 2 的 str ,自身是有编码的。 2. 「当我们创建一个新的字符串的时候,字符串会有一个指定编码,既 Python 认为这个字符串是以什么编码来存储的, Python 默认的指定编码我们可以用 sys.getdefaultencoding()函数来获取到」 sys.getdefaultencoding() 是 Python 的默认编码没错。但是创建新字符串时,字符串的编码和 Python 的默认编码没太大关系。如果字符串是从终端输入的,字符串编码是由终端编码来决定的;如果字符串是写在源码里或者从文件读取的,字符串编码是由文件编码决定的;如果字符串是从网页抓来的,字符串编码是由网页编码决定的。 Python 2 存储的就是原始编码的字符串; Python 3 会将原始字符串用判断出的编码或用户提供的编码来转换为 Unicode 字符串,只有在无法判断出编码时或用户没提供编码时才会用 sys.getdefaultencoding() 的默认编码来转换。 3. 「但是呢,字符串的实际编码并不是说 Python 指定了哪个就是哪个了,这个和系统的默认编码有关」 你这里说的「实际编码」指的是什么?是做什么用的?我没理解。 4. 「而返回的 unicode 对象的默认编码是 utf-8 。」 同上, unicode 对象是没有编码的,你可以用任何支持的编码将 unicode 对象转换为 str 对象,所以不能说 unicode 对象的默认编码是 utf-8 。 5. 「这是因为 Python 写入文件的时候将 Unicode 自动转换成了 Str ,然后这个 Str 的指定编码为 ascii ,但是实际内容却是以 utf-8 来编码的汉字,结果就是抛出编码异常了。」 这句话表述有点问题: Unicode 是没有编码的,所以不能说实际内容是以 utf-8 来编码的汉字。实际上除了 utf-8 编码,你也可以用 gbk 等编码将 unicode 的汉字转换为 str 字符串。而这里因为默认使用的 ascii 编码无法对有汉字的 unicode 字符串进行编码,所以抛出异常了。 6. 「更改 Python 默认的指定编码」 不提倡的解决方法,相关阅读: https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/ http://blog.ernest.me/post/python-setdefaultencoding-unicode-bytes /t/163786 以上仅是个人理解,不一定都是对的。 |
7
bwangel OP @imn1 ,受教了,我确实不知道 gb2312 和 gbk 还有这些差别,还有处理从外部处理字符串的,确实这些还没想过。
@Sylv @Yinz 魔幻三行的确实是不应该作为正式解决方案,我之所以叫这个叫做魔幻三行,就是当初第一次遇到这种方案,就是感觉好魔幻,这是个什么鬼。 后面六条我挨个回复一下: 1. 后来一想我感觉这个理解确实有点问题,比如一个 Str 变成 bytes :"中文".encode(),如果这里 encode 没有传入参数的话,这时默认编码会取`sys.getdefaultencoding()`,我把这个编码理解成属于 Str 的了,所以认为 Str 默认带一个编码 2. 3. 这里我的指定编码是 Python 的默认编码,实际编码就是你说的从终端,文件,网页等读取字符串时,这些输入源自己的编码,这些决定了输入字符串实际的编码。 4. 这个和第一点相同,我把`sys,getdefaultencoding()`返回的编码,认为是 Unicode 自带的属性,所以就说 Unicode 有个默认编码。 5. 好吧,这里确实有点问题。这里其实是 Unicode encode 成 str 的时候,使用了 ascii 编码,而 Unicode 中包含汉字,所以无法进行 encode |
8
bwangel OP |
10
Sylv 2016-11-10 11:33:19 +08:00 via iPhone
@bwangel
Unicode 是种字符集标准,而 UTF-8 只是实现它的编码方法之一。 Unicode 在 Python 内部是用 UCS-2 或 UCS-4 编码表示的。 UTF-8 编码是变长的,用于网络传输等情况时可以节省空间,但运行处理起来相对低效,所以 Python 的 Unicode 内部实现没有用 UTF-8 编码。 |
11
mingyun 2016-12-11 13:49:22 +08:00
s=u'中文'
obj={'s':s} print obj#输出的是对应 Unicode ,怎么输出中文 |