V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
panyanyany
V2EX  ›  Python

做了一个 python 2 & 3 处理字符串的流程图

  •  
  •   panyanyany · 2016-06-10 16:55:51 +08:00 · 5087 次点击
    这是一个创建于 3087 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这是我在阅读一些资料后总结出来的,不知道我理解得对不对 流程图

    6 条回复    2016-06-14 07:38:58 +08:00
    justou
        1
    justou  
       2016-06-10 17:59:17 +08:00
    一直用 py2 处理各种编码, 看了 5 分钟这个流程图, 最后还是没明白是啥意思
    fy
        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 编码后储存
    itlynn
        3
    itlynn  
       2016-06-10 19:09:03 +08:00 via iPhone
    在 Linux 用 Python2.7 ,终端默认就是 utf-8 ,没遇到编码的问题,杜绝 windows …
    justou
        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
    hanbaobao2005
        5
    hanbaobao2005  
       2016-06-12 13:01:27 +08:00
    python2 转换 unicode 分支的条件是什么啊?能在流程图标注一下么?谢谢
    panyanyany
        6
    panyanyany  
    OP
       2016-06-14 07:38:58 +08:00
    @hanbaobao2005 呃,没有条件,图中的分支其实是表示 “当遇到 s = u"中文" 时,会这样处理……”
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2753 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 11:42 · PVG 19:42 · LAX 03:42 · JFK 06:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.