这是我在阅读一些资料后总结出来的,不知道我理解得对不对
1
justou 2016-06-10 17:59:17 +08:00
一直用 py2 处理各种编码, 看了 5 分钟这个流程图, 最后还是没明白是啥意思
|
2
fy 2016-06-10 18:56:30 +08:00
楼主这个图太迷了,但大体差不多是这意思。
关于读取代码时的编码: 指定的 coding 最大,除此之外, py2 以系统编码为默认编码, py3 则是 utf8 关于字节串、字符串在内存中储存: py3 的字节串(bytes)与 py2 的 str 行为一致,直接将串读入内存 py3 的字符串( str )与 py2 的 unicode 行为一致,将串转为 latin1/ucs2/ucs4 编码后储存 |
3
itlynn 2016-06-10 19:09:03 +08:00 via iPhone
在 Linux 用 Python2.7 ,终端默认就是 utf-8 ,没遇到编码的问题,杜绝 windows …
|
4
justou 2016-06-10 21:51:30 +08:00 5
也写个简单总结吧
unicode 字符集说白了就是 0 到 0x10ffff 这一串数字(0 到 1114111),也叫码点, 比如汉字"中", python 中的 unicode 表示为 u'\u4e2d', \u 是转义字符, 码点是 0x4e2d(十进制为 20013). 这些数字需要转化成字节序列(0-255)在内存中表示时, 就要有一个规则将 unicode 码点(比如 0x4e2d)转换为字节序列, 这个规则就是编码, 这个过程反过来时的规则叫做解码, 另外只有 UTF 家族(UTF-8, UTF-16,...)的编码器才能将任意 unicode 码点完全正确的编码为字节序列. python 处理各种编码的一个准则: early decode, always unicode, late encode. early decode: 在获取外部输入时(文件, 终端, 网络...)尽早的将其解码为 unicode. 如果已知外部输入的编码时, 就用那个编码将输入 decode 就是; 如果不知道的话就只能靠统计的方法检测其编码了, 没有其它完全可靠的算法(但是 utf 编码的可以直接检测 BOM), 比如大多数浏览器自动检测编码就是靠统计, 最后以某个大概率统计出具体编码, python 的一个扩展库 chardet 也是基于统计, 如果是写爬虫的话, chardet 几乎是一个必须的库吧(requests 都直接把 chardet 放在自己的包里面了), 如果是读取本地文件, py2 要依赖标准库的 codecs 解码, py3 的 open 函数自带解码参数 always unicode: 程序内部处理过程中都统一为 unicode late encode: 程序处理完, 需要将其输出了, 无论输出在终端是还是在文件, 都是给人看的, 需要将 unicode 码点转换为字节序列, 比如说简中 windows 的控制台吧, 默认代码页是 cp932, 编码数大概是 23,940 个(跟 unicode 的 1114112 个比较下就知道为啥好多字符都不能显示在控制台了), 显示在控制台一般能起个简单观测的作用, 可以简单的 ignore 掉不能显示的字符 eg: --------------------------------------------------------------------------------------------------------------------------------------------- # -*- encoding = utf-8 -*- # 上面这一行的作用是提示 python 虚拟机, 它将要读取的这个代码文件是 utf-8 编码的.因为这里面会有英语以外的字符 # 这不是强制的, 如果虚拟机发现不是 utf-8 编码的, 会用默认的 ascii 读取该代码文件, 于是有不是英文的字符就会报错 # 当然你也必须保存为 utf-8, 而且是有 BOM(Byte Order Mark)的 utf-8 文件, 试试用其它编辑器改成 No BOM 或者 # 其它编码, 虚拟机检测不到文件的 BOM, 也转为使用 ascii 解码并读取该文件 import locale local_encoding = locale.getpreferredencoding() # 获取控制台默认编码, 不一定是 cp932 呀 print local_encoding alice = u"アリス・マーガトロイド" # 这个日文的点・在 cp936 的控制台是显示不出来的, 如果想在控制台显示这个字符串, # 可以在编码时选择 ignore 不能编码的字符,或者 replace(默认使用?替换) try: print alice except Exception as e: print e print alice.encode(local_encoding, errors="ignore") --------------------------------------------------------------------------------------------------------------------------------------------- 用 windows 终端运行看看吧, 当然在 IDE 中 print alice 可能能完整显示, 因为输出被重定向了 ------------------------------------------ 在 python 自带的 IDLE 中运行的结果: cp936 アリス・マーガトロイド アリスマーガトロイド IDLE 中输出被重定向, 点正确显示 使用 cp936 编码后点被 ignore 了 ---------------------------------------- 控制台运行的结果: cp936 'gbk' codec can't encode character u'\u30fb' in position 3: illegal multibyte sequence アリスマーガトロイド 编码失败 忽略不能编码的码点 输出到文件跟输出到控制台是一样的, 都是需要某个具体编码的地方, 当然这时可以指定能完全编码 unicode 的 UTF 系列编码器完全无误的记录下来. 文本的编码解码可以类比音视频的编码解码, 比如用一个音乐播放器播放视频, 解码器给错, 当然不能播放,decode error; 压制视频的时候, 给 video 指定一个 audio 的编码器, encode error |
5
hanbaobao2005 2016-06-12 13:01:27 +08:00
python2 转换 unicode 分支的条件是什么啊?能在流程图标注一下么?谢谢
|
6
panyanyany OP @hanbaobao2005 呃,没有条件,图中的分支其实是表示 “当遇到 s = u"中文" 时,会这样处理……”
|