zoukankan      html  css  js  c++  java
  • Python encode和decode

    今天在写一个StringIO.write(int)示例时思维那么一发散就拐到了字符集的问题上,顺手搜索一发,除了极少数以外,绝大多数中文博客都解释的惨不忍睹,再鉴于被此问题在oracle的字符集体系中蹂躏过,因此在过往笔记的基础上增删了几个示例贴出来。

    Python2:

    首先清楚两个Python 2中的概念:str和unicode 这是python2中的两种用于表示文本的类型,一般来说你直接打出的字符都属于前者,加了u前缀的字符则属于后者。

      str is text representation in bytes, unicode is text representation in characters.

    此观点来自stackoverflow,是得票最多的一个回答,也是我认为最好的一个,但是从我个人的角度来看这个表述依然不足,最适合的表述应当是:

      str is text representation in bytes, unicode is text representation in unicode characters(or unicode bytes).

    貌似没多大区别......可能会被人打,但我的意思是python2里的unicode是字符和编码绑定的,只要是unicode类型那么他的编码和字符都已经固定了,但是str类型却只有编码,只有最初打出它的人才知道他的字符是什么(或者说才能通过适当的字符集解码为人眼可懂的字符)。

    Python2里的str是十六进制表示的二进制编码,unicode是一个字符:
    通俗点来说就是Python2里的str类型是一堆二进制编码,如果不知道是什么字符集那么你除了一堆十六进制
    数什么都看不出来(当然平时你使用的工具都是能看到的,因为工具已经做了转码),通过decode可以将其按固定的字符集解码,生成unicode字符。
    例如下例(python2环境下的windows cmd窗口):
    >>> a='你好'
    >>> a.decode('utf-8')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "C:Python27libencodingsutf_8.py", line 16, in decode
        return codecs.utf_8_decode(input, errors, True)
    UnicodeDecodeError: 'utf8' codec can't decode byte 0xc4 in position 0: invalid continuation byte
    错误的原因是这里的“你好”字符是cp936编码(相当于gbk),utf-8属于非ANSI体系的编码,“你好”的gbk二进制码不符合unicode体系的编码规则因此报错。
    >>> print a.decode('gbk'),type(a.decode('gbk'))
    你好 <type 'unicode'>
    这样就可以啦,既然a是gbk编码的str那么按gbk进行decode解码,自然能得到unicode的你好字符。
    decode: str to unicode,decode的输入必须是str类型,输出一定是unicode类型
    str.decode(encoding='UTF-8',errors='strict')
    ​
    encode: unicode to str,encode的输入必须是unicode类型,输出一定是str类型
    unicode_char.encode(encoding='gbk',errors='strict')

    Python3:

    在Python3中str调用decode()方法会遇到: AttributeError: 'str' object has no attribute 'decode' .

    why?

    这是因为python3中表示文本的只有一种类型了,那就是str,你以为这是python2里的那个str吗?No! 这个str是python2中的unicode类型......

    那么原来的str哪里去了?被命名为bytes类型了,decode方法也随之给了bytes类型,encode给了str类型。

     这样做的好处是:

    在Python2中str和unicode都有decode,encode两种方法,但是字符集参数不设置正确的话,函数经常报错,文本能否正确流通取决于大家是否清楚输入编码的字符集,这对于全球化的网站来说是个巨坑,而在Python3中无论你输入什么字符,统一都是str类型的(也就是python2里的unicode类型),通过bytes和str类型的分离将decode,encode这两种方法分离,encode函数不会出错,因为编码与字符集是绑定的,你可以随意将unicode字符转化为任意ANSI体系字符集的bytes类型,此时在已知ANSI字符集的情况下,你对bytes类型的decode转码一定不会出错。通过这种方式就避免了python2中输入str类型带来的编码混乱问题。

    [root@python ~]# python3
    Python 3.6.5 (default, Apr  9 2018, 17:15:34) 
    [GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> a='你好'
    >>> type(a)
    <class 'str'>
    >>> a.encode('gbk')
    b'xc4xe3xbaxc3'
    >>> type(a.encode('gbk'))
    <class 'bytes'>
    通过encode方式我们可以把unicode字符转为任意字符集的bytes类型,这种bytes类型可以通过decode()来重新转为unicode。

    使用相似的观点来表述Python3中的bytes和str的区别就是:

     bytes is text representation in bytes only if you know the charset, str is text representation in unicode characters(or unicode bytes).

  • 相关阅读:
    如何优雅地删除 Linux 中的垃圾文件
    session:
    cookie:
    多对多表结构设计:
    接口测试:
    oracle基本笔记整理
    oracle基本笔记整理
    oracle基本笔记整理
    2016年寒假心得
    2016年寒假心得
  • 原文地址:https://www.cnblogs.com/leohahah/p/10220991.html
Copyright © 2011-2022 走看看