zoukankan      html  css  js  c++  java
  • Python 3中的编码

    Python 3中的默认编码

    Python3中默认是UTF-8

    可查看Python3的默认编码。

    >>> import sys
    >>>
    >>> sys.getdefaultencoding()
    'utf-8'
    >>>

    系统默认编码 指:
    在python 3编译器读取.py文件时,若没有头文件编码声明,则默认使用“utf-8”来对.py文件进行解码。并且在调用 encode()这个函数时,不传参的话默认是“ utf-8 ”。(这与下面的open( )函数中的“encoding”参数要做区分

    本地默认编码 指:
    在你编写的python 3程序时,若使用了 open( )函数 ,而不给它传入 “ encoding ” 这个参数,那么会自动使用本地 Windows 或 Linux 的默认编码。没错,如果在Windows系统中,就是默认用gbk格式所以请大家在这里注意:linux中可以不用传“ encoding” 的参数, 而win中不能忘了“ encoding” 的参数

    utf-8是可变长的的编码,有1个字节的英文字符,也有2个字节的阿拉伯文,也有3个字节的中文和日文。utf-8是有严格定义的,一个字节的字符高位必须是0;三个字节的字符中,第一个字节的高位是1110开头。   
        
    gbk对英文是使用单字节编码(也就意味着兼容ascii),而gbk对中文部分是采取定长的2字节,总体编码范围为 8140-FEFE,首字节在 81-FE 之间,尾字节在 40-FE 之间。所以说它只要没有碰到尾字节在40之内的字符,都会一股脑地按照2字节去解码成中文。而中文在 utf-8 编码后,一般是三字节的。当解码的字节数和编码的字节数不匹配时,自然会造成全是乱码的局面。

    实际上unicode就是一个字符集,一个字符与数字一一对应的映射关系,因为它一律以2个字节编码(或者也有4个字节的,这里不讨论),所以占用空间会大一些,一般只用于内存中的编码使用。
    而 utf-8 是为了实现unicode 的传输和存储的。因为它可变长,存英文时候可以节省大量存储空间。传输时候也节省流量。

    进程在内存中的表现是“ unicode ”的编码;当python3编译器读取磁盘上的.py文件时,是默认使用“utf-8”的;当进程中出现open(), write() 这样的存储代码时,需要与磁盘进行存储交互时,则是默认使用操作系统的默认编码。

     

    Python 3中的​encode和decode

    Python3中字符编码经常会使用到decode和encode函数。特别是在抓取网页中,这两个函数用的熟练非常有好处。encode的作用,使我们看到的直观的字符转换成计算机内的字节形式。decode刚好相反,把字节形式的字符转换成直观的形式。

    >>> "西安".encode()
    b'\xe8\xa5\xbf\xe5\xae\x89'
    >>> b'\xe8\xa5\xbf\xe5\xae\x89'.decode()
    '西安'

    \x表示后面是十六进制

    在Python 3中, 以字节形式表示的字符串则必须加上前缀b,也就是写成上文的b'xxxx'形式。

     ​UTF-8兼容ASCII

    Python3中的​编码转换

     字符以Unicode的字节形式表现出来

    >>> "西安".encode('unicode-escape')
    b'\\u897f\\u5b89'
    >>> b'\\u897f\\u5b89'.decode('unicode-escape')
    '西安'

    如果我们知道一个Unicode字节码,怎么变成UTF-8的字节码,先decode,再encode。

    >>> "西安".encode('unicode-escape')
    b'\\u897f\\u5b89'
    >>> "西安".encode('unicode-escape').decode('unicode-escape')
    '西安'
    >>> "西安".encode('unicode-escape').decode('unicode-escape').encode()
    b'\xe8\xa5\xbf\xe5\xae\x89'

    源代码文件中,如果有用到非ASCII字符,则需要在文件头部进行字符编码的声明,如下:

    #-*- coding: UTF-8 -*-

       

     python3中的字符序列也有两种类型:bytes和str。python3中的bytes和python2中的str相似,str和python2中的unicode相似。这里要注意,str类型在python3和python2中都有,但含义完全变了。

    unicode_string=u'中国'
    print(len(unicode_string))
    print( type(unicode_string))
    str_string = unicode_string.encode('utf-8')
    print(len(str_string))
    str_string
    print(type(str_string))
    
    
    >>> unicode_string=u'中国'
    >>> print(len(unicode_string))
    2
    >>> print( type(unicode_string))
    <class 'str'>
    >>> str_string = unicode_string.encode('utf-8')
    >>> print(len(str_string))
    6
    >>> str_string
    b'\xe4\xb8\xad\xe5\x9b\xbd'
    >>> print(type(str_string))
    <class 'bytes'>

    UnicodeEncoderError
    将文本转化为字节序列时,若有字符在目标编码中没有定义,则会出现UnicodeEncoderError。
    由于中文字符在ascii编码中无定义,则会报出编码错误。对于此类问题,需选择合适的编码类型,比如含有中文字符,一般用UTF-8编码类型对unicode字符串编码。

    >>> unicode_string=u'平国'
    >>> unicode_string.encode('ascii')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)



    UnicodeDecodeError
    把二进制序列转化为文本时,遇到无法转换的字节序列,则会发生此异常。比如用UTF-8编码后的二进制序列,用GB2312解码,由于两种编码不兼容,用GB2312不能识别字节序列,则会出现异常。

    unicode_string=u'中国'
    utf8_string=unicode_string.encode('utf-8')
    utf8_string.decode('GB2312')



    碰到这种异常,是由于decode使用的编码和字节序列的编码不一致,可以用字符编码侦测包chardet检测字节序列的编码,然后再用此编码解码。

    import chardet  ### pip install chardet
    utf8_string=u"中国"
    str_type=chardet.detect(utf8_string)
    str_type
    #python 3,str和bytes类型相互转换工具类
    #file:python3_endecode_helper.py
    def to_str(bytes_or_str):
        if isinstance(bytes_or_str,bytes):
            value = bytes_or_str.decode('UTF-8')
        else:
            value = bytes_or_str
        return value
    
    def to_bytes(bytes_or_str):
        if isinstance(bytes_or_str,str):
            value = bytes_or_str.encode('UTF-8')
        else:
            value = bytes_or_str
        return value
    
    if __name__=='__main__':
        str_string = u'中国'
        value = to_bytes(str_string)
        print(type(value)) #<class 'bytes'>
        value = to_str(value)
        print(type(value)) #<class 'str'>



    # coding:gbk
    
    import sys
    import locale
    
    def p(f):
        print('%s.%s(): %s' % (f.__module__, f.__name__, f()))
    
    # 返回当前系统所使用的默认字符编码
    p(sys.getdefaultencoding)
    
    # 返回用于转换Unicode文件名至系统文件名所使用的编码
    p(sys.getfilesystemencoding)
    
    # 获取默认的区域设置并返回元组(语言, 编码)
    p(locale.getdefaultlocale)
    
    # 返回用户设定的文本数据编码
    # 文档提到this function only returns a guess
    p(locale.getpreferredencoding)
    
    # 在笔者的Windows上的结果
    # sys.getdefaultencoding(): utf-8
    # sys.getfilesystemencoding(): utf-8
    # locale.getdefaultlocale(): ('en_US', 'cp936')
    # locale.getpreferredencoding(): cp936

    REF

    https://www.cnblogs.com/killianxu/p/9746545.html

    https://www.cnblogs.com/huxi/archive/2010/12/05/1897271.html

    https://blog.csdn.net/ym01213/article/details/89083428

    https://zhuanlan.zhihu.com/p/40834093

  • 相关阅读:
    纯CSS制作二级导航
    用python写MapReduce函数——以WordCount为例
    hadoop安装配置——伪分布模式
    字符串中最长不重合子串长度
    从30岁到35岁:为你的生命多积累一些厚度
    Hbase快速开始——shell操作
    5句话
    []leetcode]Unique Paths II
    [leetcode]Gray Code
    linux 命令案例学习——文件搜索
  • 原文地址:https://www.cnblogs.com/emanlee/p/15640983.html
Copyright © 2011-2022 走看看