澳门新萄京官方网站-www.8455.com-澳门新萄京赌场网址

文本和字节序列,编码格式

2019-07-15 作者:www.8455.com   |   浏览(176)

本文首要内容

文本和字节序列,编码格式。字符

澳门新萄京官方网站,字节

结构体和内部存款和储蓄器视图

字符和字节之间的转移——编解码器

BOM鬼符

    标准化Unicode字符串

  Unicode文本排序

 

python高级——目录

文中代码均位于github上:https://github.com/ampeeg/cnblogs/tree/master/python高级

 

python高档(四)—— 文本和字节体系(编码难点),python字节

字符难题

Unicode 标准把字符的标记和具体的字节表述进行了明显区分

  • 字符的标记,即码位,是0-1114111的数字(十进制)
  • 编码是在码位与字节连串之间转移时行使的算法。
    把码位调换为字节体系是编码,把字节系列转为码位是解码

  Python 3 显著区分了人类可读的文本字符串和原本的字节体系。隐式地把字节类别调换成Unicode 文本已成过去。

--内容出自廖雪峰的python3.x教程,invert your own computer 加梅斯with python,python核心编制程序

字符

'''
    字符编码问题是经常困扰python编程人员的问题,我在编写爬虫的过程中也经常遇到这个头疼的事。

    从python3开始,明确区分了人类语言(文本字符串)和机器语言(二进制字节),咱们先说文本字符串
    开始之前,得对"字符"进行定义:
        字符:Unicode字符,从python3的str对象中获取的元素是Unicode字符
        字符串:字符串就是一个字符序列(这里对于(一)中内容相呼应)

'''


if __name__ == "__main__":
    # 创建字符
    s1 = str('a')
    s2 = 'b'
    s3 = u'c'
    print(s1, s2, s3)      # a b c

   

  此时只用记住在python3中字符就是unicode,也正是str是unicode,那是人类能够看懂的语言。

 

本文首要内容

字符

字节

结构体和内部存款和储蓄器视图

字符和字节之间的改动——编解码器

BOM鬼符

   前天持续。。。

 

python高级——目录

文中代码均位于github上:

 

字节概要

python内置了二种基本的二进制系列类型:

  • bytes:python3引进的不足变类型
  • bytearray: 可变类型
    bytes或bytearray对象的逐条要素是介于0-255(含)之间的大背头。二进制体系的切成丝始终是一模一样品种的二进制连串,包括长度为1的切条。
    就算二进制类别其实是整数体系,可是它们的字面量表示法表明在那之中有ASCII文本。因而,各样字节的值也许会利用下列三种不一致的法子展现。
  • 可打字与印刷的ASCII范围内的字符(从空格到~)。使用ASCII字符自己。
  • 制表符,换行符,回车符和 对应的字节,使用转义连串t,n,r.
  • 其余字节的值,使用十六进制转义类别(举例, x00是空字节)
    营造bytes或bytearray实例还是能调用各自的构造方法,传入下述参数。
  • 三个str对象和三个encoding关键字参数
  • 一个可迭代对象,提供0~255之间的数值。
  • 二个偏分头,使用空字节创造对应长度的二进制种类。python3.6会将其除去
  • 二个完毕了缓冲协议的指标(如bytes,bytearray,memoryview,array.array);此时,把源对象中的字节种类复制到新建的二进制种类中.
    在意 - 使用缓冲类对象成立bytes只怕bytearray对象时,始终复制源对象中的字节类别。与之相反,memoryview对象允许在二进制数据结构之间分享内存。

  深远理解Unicode 对你大概那三个根本,也可能无关主要,那取决Python 编制程序的情景。提及底,本章涵盖的标题对只管理 ASCII 文本的程序猿未有影响。但是固然如此,也不可能避开不谈字符串和字节系列的分别。其它,你会发现特意的二进制系列类型所提供的成效,有些是Python 2 中“全职能”的 str 类型不具备的。

编码格式

ASCII编码和Unicode编码的界别:ASCII编码是1个字节,而Unicode编码日常是2个字节

字母A用ASCII编码是十进制的65,二进制的0一千001。

如果把ASCII编码的A用Unicode编码,只需求在头里补0就足以,因此,A的Unicode编码是00000000 01000001。

主题素材出现了:假若统一成Unicode编码,乱码难点之后未有了。但是,若是写的文本基本上全数是罗马尼亚(România)语的话,用Unicode编码比ASCII编码要求多一倍的蕴藏空间,在积存和传导上就老大不划算。

进而,本着节约的旺盛,又并发了把Unicode编码转化为“可变长编码”的UTF-8编码。UTF-8编码把二个Unicode字符依据不一样的数字大我码成1-6个字节,常用的塞尔维亚(Република Србија)语字母被编码成1个字节,汉字常常是3个字节,独有很素不相识的字符才会被编码成4-6个字节。假设您要传输的文件包罗大量德文字符,用UTF-8编码就能够节约空间:

   字符            ASCII                       Unicode                                                 UTF-8


     A             01000001           00000000 01000001                                    01000001


     中                     /                 01001110 0010110111100100                10111000 10101101


UTF-8包容ASCII,所以UTF-8能够合作那多少个那多少个老旧编码的软件。

驾驭了三者的联系后,大家谈谈当代管理器中通用的编码格式:

澳门新萄京官方网站 1

图1 内存<->文本

内存中联合用unicode编码,当必要保留只怕传输到设备时转为UTF-8编码。用记事本编辑的时候,从文件读取的UTF-8字符被改变为Unicode字符到内部存款和储蓄器里,编辑达成后,保存的时候再把Unicode调换为UTF-8保存到文件。

澳门新萄京官方网站 2

图2 网页浏览

浏览网页时,服务器会把unicode编码的数目转化成UTF-8传输给浏览器,所以大家能够到看到众多网页都会有<meta charset='utf-8' />

字节

'''
    python3中内置有两种基本的二进制序列类型:不可变的bytes和可变bytearray
        (1)bytes和bytearray的各个元素是介于0~255(8个bit)之间的整数;
        (2)二进制序列的切片始终是同一类型的二进制序列
'''


if __name__ == "__main__":
    # 创建bytes 和 bytearray
    b1 = bytes('abc你好', encoding='utf8')      # 关于encode稍后会说,不知道有没有人和我一样总是将编码与解码的方向混淆
    print(b1)          # b'abcxe4xbdxa0xe5xa5xbd'

    b2 = bytearray('abc你好', encoding='utf8')
    print(b2)          # bytearray(b'abcxe4xbdxa0xe5xa5xbd')

    # 切片(提示:序列都可以切片)
    print(b1[3:5])     # b'xe4xbd'
    print(b2[3:5])     # bytearray(b'xe4xbd')

    # 使用列表取值的方法试试
    print(b1[3])       # 228 此时取出来的就不是字节序列了,而是一个元素
    for _ in b1:
        print(_, end=',')   # 97,98,99,228,189,160,229,165,189,      这都是8bit的整数

    # bytes的不可变 vs. bytearray的可变

    # b1[3] = 160           # 报错:'bytes' object does not support item assignment
    print(id(b2), b2)      # 4373768376 bytearray(b'abcxe4xbdxa0xe5xa5xbd')
    b2[2] = 78
    print(id(b2), b2)      # 4373768376 bytearray(b'abNxe4xbdxa0xe5xa5xbd')

    # 将b2转换成字符串看看
    print(b2.decode('utf8'))  # abN你好
                              # 注意,这里之所以能够用utf8转成unicode,是因为N的ascii码和utf8一致
    b2.extend(bytearray('添加的内容', encoding='utf8'))  # 既然是可变序列,bytearray当然拥有一般的序列的方法
    print(id(b2), b2)         # 4373768376 bytearray(b'abNxe4xbdxa0xe5xa5xbdxe6xb7xbbxe5x8axa0xe7x9ax84xe5x86x85xe5xaexb9')

    print(b2.decode('utf8'))  # abN你好添加的内容

    # PS:大家可以将二进制序列当成列表,元素就是ascii编码(0~255)

 

字符

'''
    字符编码问题是经常困扰python编程人员的问题,我在编写爬虫的过程中也经常遇到这个头疼的事。

    从python3开始,明确区分了人类语言(文本字符串)和机器语言(二进制字节),咱们先说文本字符串
    开始之前,得对"字符"进行定义:
        字符:Unicode字符,从python3的str对象中获取的元素是Unicode字符
        字符串:字符串就是一个字符序列(这里对于(一)中内容相呼应)

'''


if __name__ == "__main__":
    # 创建字符
    s1 = str('a')
    s2 = 'b'
    s3 = u'c'
    print(s1, s2, s3)      # a b c

文本和字节序列,编码格式。   

  此时只用记住在python3中字符正是unicode,也等于str是unicode,这是人类能够看懂的语言。

 

结构体和内部存款和储蓄器视图

struct模块提供了一部分函数,能管理bytes,bytearray和memoryview对象。

 

python字符串

python3中的字符串是unicode编码,所以辅助多国语言。

ord()函数获取字符编码整数,chr()则赶回对应字符。

澳门新萄京官方网站 3

图3 函数示例

python中字符串类型是str,代表二个或多少个字节。若是急需传输大概封存,要求选拔bytes品种数据。对bytes连串的数码的拍卖,python是那样表示的:

byt = b"string"

“string”和b“string”是有分别的。

Unicode代表的str可以经过encode()方法成为bytes类型。

澳门新萄京官方网站 4

图4 encode示例图

纯马耳他语的str能够用ASCII编码为bytes,内容是大同小异的,含有中文的str能够用UTF-8编码为bytes。含有汉语的str不可能用ASCII编码,因为普通话编码的限定当先了ASCII编码的限定,Python会报错。

在bytes中,一点都不大概展现为ASCII字符的字节,用x##显示。

转头,假诺大家从网络或磁盘上读取了字节流,那么读到的数目便是bytes。要把bytes变为str,就必要用decode()方法。

出于Python源代码也是叁个文件文件,所以,当您的源代码中蕴藏汉语的时候,在保存源代码时,就要求务必钦点保存为UTF-8编码。当Python解释器读取源代码时,为了让它按UTF-8编码读取,大家平时在文件开首写上这两行:

#!/usr/bin/env python3

# -- coding: utf-8 -*-*

率先行注释是为着告诉Linux/OS X系统,那是一个Python可试行程序,Windows系统会忽视那个注释;

第二行注释是为着告诉Python解释器,依据UTF-8编码读取源代码,不然,你在源代码中写的国语输出恐怕会有乱码。

发明了UTF-8编码并不表示你的.py文件正是UTF-8编码的,必须同一时候要保险文本编辑器正在利用UTF-8 without BOM编码。

结构体和内部存款和储蓄器视图

'''
    struct可以从二进制序列中提取结构化信息。
    struct模块提供了一些函数,可以将打包的字节序列转换成不同类型字段组成的元组;还有一些函数用于执行反向转换。
    struct模块可以处理bytes、bytearray、memoryview对象。
'''

import struct

if __name__ == "__main__":
    # memoryview类用于共享内存,可以访问其他二进制序列、打包的数组和缓冲中的数据切片,该操作无需赋值字节序列
    fmt = '<3s3sHH'   # 设置格式,< 是小字节序,3s3s是两个3字节序列,HH是两个16位二进制整数

    with open('L3_图_python.jpg', 'rb') as f:     # 需要在github中下载后运行
        img = memoryview(f.read())

    print(bytes(img[:10]))    # b'xffxd8xffxe0x00x10JFIFx00x01x01x02x00x1cx00x1cx00x00'
    print(struct.unpack(fmt, img[:10]))   # (b'xffxd8xff', b'xe0x00x10', 17994, 17993)  :拆包

    del img

 

字节

'''
    python3中内置有两种基本的二进制序列类型:不可变的bytes和可变bytearray
        (1)bytes和bytearray的各个元素是介于0~255(8个bit)之间的整数;
        (2)二进制序列的切片始终是同一类型的二进制序列
'''


if __name__ == "__main__":
    # 创建bytes 和 bytearray
    b1 = bytes('abc你好', encoding='utf8')      # 关于encode稍后会说,不知道有没有人和我一样总是将编码与解码的方向混淆
    print(b1)          # b'abcxe4xbdxa0xe5xa5xbd'

    b2 = bytearray('abc你好', encoding='utf8')
    print(b2)          # bytearray(b'abcxe4xbdxa0xe5xa5xbd')

    # 切片(提示:序列都可以切片)
    print(b1[3:5])     # b'xe4xbd'
    print(b2[3:5])     # bytearray(b'xe4xbd')

    # 使用列表取值的方法试试
    print(b1[3])       # 228 此时取出来的就不是字节序列了,而是一个元素
    for _ in b1:
        print(_, end=',')   # 97,98,99,228,189,160,229,165,189,      这都是8bit的整数

    # bytes的不可变 vs. bytearray的可变

    # b1[3] = 160           # 报错:'bytes' object does not support item assignment
    print(id(b2), b2)      # 4373768376 bytearray(b'abcxe4xbdxa0xe5xa5xbd')
    b2[2] = 78
    print(id(b2), b2)      # 4373768376 bytearray(b'abNxe4xbdxa0xe5xa5xbd')

    # 将b2转换成字符串看看
    print(b2.decode('utf8'))  # abN你好
                              # 注意,这里之所以能够用utf8转成unicode,是因为N的ascii码和utf8一致
    b2.extend(bytearray('添加的内容', encoding='utf8'))  # 既然是可变序列,bytearray当然拥有一般的序列的方法
    print(id(b2), b2)         # 4373768376 bytearray(b'abNxe4xbdxa0xe5xa5xbdxe6xb7xbbxe5x8axa0xe7x9ax84xe5x86x85xe5xaexb9')

    print(b2.decode('utf8'))  # abN你好添加的内容

    # PS:大家可以将二进制序列当成列表,元素就是ascii编码(0~255)

 

主干的编解码器

utf-8之类的

字符难题

字符和字节之间的转移——编解码器

'''
    python自带有超过100中编解码器,用于在字符串和字节之间相互转换。
    每个编码都有多个名称,例如'utf_8'、'utf8'、'utf-8'、'U8',这些都可以传递给open()、str.encode()、bytes.decode()中的
    encoding参数
'''


if __name__ == "__main__":
    # 看看不同的编码效果
    for codec in ['gbk', 'utf8', 'utf16']:
        print(codec, "你好".encode(codec), sep='t')
    '''
                        gbk      b'xc4xe3xbaxc3'
                        utf8    b'xe4xbdxa0xe5xa5xbd'
                        utf16    b'xffxfe`O}Y'
    '''
    # 咱们再来解码
    print(b'xc4xe3xbaxc3'.decode('gbk'))            # 你好
    print(b'xe4xbdxa0xe5xa5xbd'.decode('utf8'))   # 你好
    print(b'xffxfe`O}Y'.decode('utf16'))              # 你好
'''
    遇到编码问题一般很烦躁,下面来看看一般怎么解决编码问题。
    (1)UnicodeEncodeError
     (2) UnicodeDecodeError
'''



if __name__ == "__main__":
    # (1)UnicodeEncodeError
    # 使用errors参数
    s1 = "hello,你长胖啦".encode('latin-1', errors='ignore')
    print(s1)   # b'hello'    使用 errors='ignore' 忽略了无法编码的字符

    s2 = "hello,你长胖啦".encode('latin-1', errors='replace')
    print(s2)   # b'hello?????'    使用errors='replace'将无法编码的字符用问好代替

    s3 = "hello,你长胖啦".encode('latin-1', errors='xmlcharrefreplace')
    print(s3)   # b'hello&#65292;&#20320;&#38271;&#32982;&#21862;'  使用errors='xmlcharrefreplace'将无法编码的内容替换成XML实体

    # (2) UnicodeDecodeError
    # 乱码字符称为鬼符,以下实例演示出现鬼符的情况

    s4 = b'Montrxe9al'
    print(s4.decode('cp1252'))    # Montréal
    print(s4.decode('iso8859_7')) # Montrιal
    print(s4.decode('koi8_r'))    # MontrИal
    #print(s4.decode('utf8'))      # 报错:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 5: invalid continuation byte
    print(s4.decode('utf8', errors='replace'))   # Montr�al
    '''
        大多数人都遇到过乱码问题,并且可能总是调试不成功,这可能是各种程序之间的编码不匹配
        以下代码引用自<流畅的python>,可以用来查看当前环境的一些默认编码     
    '''

    # -*- coding: utf-8 -*-

    import sys, locale

    expressions = """
            locale.getpreferredencoding()
            type(my_file)
            my_file.encoding
            sys.stdout.isatty()
            sys.stdout.encoding
            sys.stdin.isatty()
            sys.stdin.encoding
            sys.stderr.isatty()
            sys.stderr.encoding
            sys.getdefaultencoding()
            sys.getfilesystemencoding()
        """

    my_file = open('dummy', 'w')

    for expression in expressions.split():
        value = eval(expression)
        print(expression.rjust(30), '->', repr(value))

    '''
        我电脑运行结果如下:
        (' locale.getpreferredencoding()', '->', "'UTF-8'")
        ('                 type(my_file)', '->', "<type 'file'>")
        ('              my_file.encoding', '->', 'None')
        ('           sys.stdout.isatty()', '->', 'True')
        ('           sys.stdout.encoding', '->', "'UTF-8'")
        ('            sys.stdin.isatty()', '->', 'True')
        ('            sys.stdin.encoding', '->', "'UTF-8'")
        ('           sys.stderr.isatty()', '->', 'True')
        ('           sys.stderr.encoding', '->', "'UTF-8'")
        ('      sys.getdefaultencoding()', '->', "'ascii'")
        ('   sys.getfilesystemencoding()', '->', "'utf-8'")
    '''

结构体和内部存款和储蓄器视图

'''
    struct可以从二进制序列中提取结构化信息。
    struct模块提供了一些函数,可以将打包的字节序列转换成不同类型字段组成的元组;还有一些函数用于执行反向转换。
    struct模块可以处理bytes、bytearray、memoryview对象。
'''

import struct

if __name__ == "__main__":
    # memoryview类用于共享内存,可以访问其他二进制序列、打包的数组和缓冲中的数据切片,该操作无需赋值字节序列
    fmt = '<3s3sHH'   # 设置格式,< 是小字节序,3s3s是两个3字节序列,HH是两个16位二进制整数

    with open('L3_图_python.jpg', 'rb') as f:
        img = memoryview(f.read())

    print(bytes(img[:10]))    # b'xffxd8xffxe0x00x10JFIFx00x01x01x02x00x1cx00x1cx00x00'
    print(struct.unpack(fmt, img[:10]))   # (b'xffxd8xff', b'xe0x00x10', 17994, 17993)  :拆包

    del img

 

精通编码难题

  • UnicodeEncodeError: 把字符串转成二进制种类时
  • UnicodeDecodeError: 把二进制连串转变为字符串时
  • SyntaxError: 源码的编码与预期不符。

  在 二〇一五 年,“字符”的特级定义是 Unicode 字符。由此,从 Python 3 的str 对象中获得的要素是 Unicode 字符,这一定于从 Python 2 的unicode 对象中得到的元素,实际不是从 Python 2 的 str 对象中赢得的原始字节连串。

BOM鬼符

 ''' 关于BOM的内容比较底层,以下内容全部选自<流畅的python> ''' 

 

字符和字节之间的转换——编解码器

'''
    python自带有超过100中编解码器,用于在字符串和字节之间相互转换。
    每个编码都有多个名称,例如'utf_8'、'utf8'、'utf-8'、'U8',这些都可以传递给open()、str.encode()、bytes.decode()中的
    encoding参数
'''


if __name__ == "__main__":
    # 看看不同的编码效果
    for codec in ['gbk', 'utf8', 'utf16']:
        print(codec, "你好".encode(codec), sep='t')
    '''
                        gbk      b'xc4xe3xbaxc3'
                        utf8    b'xe4xbdxa0xe5xa5xbd'
                        utf16    b'xffxfe`O}Y'
    '''
    # 咱们再来解码
    print(b'xc4xe3xbaxc3'.decode('gbk'))            # 你好
    print(b'xe4xbdxa0xe5xa5xbd'.decode('utf8'))   # 你好
    print(b'xffxfe`O}Y'.decode('utf16'))              # 你好
'''
    遇到编码问题一般很烦躁,下面来看看一般怎么解决编码问题。
    (1)UnicodeEncodeError
     (2) UnicodeDecodeError
'''



if __name__ == "__main__":
    # (1)UnicodeEncodeError
    # 使用errors参数
    s1 = "hello,你长胖啦".encode('latin-1', errors='ignore')
    print(s1)   # b'hello'    使用 errors='ignore' 忽略了无法编码的字符

    s2 = "hello,你长胖啦".encode('latin-1', errors='replace')
    print(s2)   # b'hello?????'    使用errors='replace'将无法编码的字符用问好代替

    s3 = "hello,你长胖啦".encode('latin-1', errors='xmlcharrefreplace')
    print(s3)   # b'hello&#65292;&#20320;&#38271;&#32982;&#21862;'  使用errors='xmlcharrefreplace'将无法编码的内容替换成XML实体

    # (2) UnicodeDecodeError
    # 乱码字符称为鬼符,以下实例演示出现鬼符的情况

    s4 = b'Montrxe9al'
    print(s4.decode('cp1252'))    # Montréal
    print(s4.decode('iso8859_7')) # Montrιal
    print(s4.decode('koi8_r'))    # MontrИal
    #print(s4.decode('utf8'))      # 报错:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 5: invalid continuation byte
    print(s4.decode('utf8', errors='replace'))   # Montr�al

 

  前几天连任。。。

处理公事文件

管理公事的极品实施是‘Unicode吉安治’。

  • 及早把输入(举例读取文件)的字节体系解码成字符串。
  • 在别的管理进度中,一定不能编码或解码
  • 对出口来讲,则要尽量晚的把字符串编码成字节类别。

举个  编码和解码

标准化Unicode字符串

'''
    初一看这个标题可能会有点蒙,难道Unicode本身还不够标准么?
    先看看以下的例子:
'''
s1 = 'café'
s2 = 'cafeu0301'
print(s1, s2)     # café café
print(s1 == s2)   # False

'''
    我们发现café可以用'café'和'cafeu0301'两种方式表示,这个词对于人来说是一样的,但是这两种表示对于计算机来说确实不一样的
    向这样的序列叫"标准等价物",在计算机中存储的值不相等,但应用程序应该认为相等。

    要解决这个问题,需要用到unicodedata.nomalize函数,它的第一个参数可以选择这四种形式的一个:"NFC"、"NFD"和"NFKC"、"NFKD"
        "NFC":使用最少的码为构成等价的字符串
        "NFD":把组合的字符分割成基本字符和单独的组合字符

        "NFKC"&"NFKD":这两种是较严格的规范形式,对"兼容字符有影响"
'''

from unicodedata import normalize

if __name__ == "__main__":
    # "NFC" & "NFD"
    print(s1.encode('utf8'), s2.encode('utf8'))   # b'cafxc3xa9' b'cafexccx81'
    s1 = normalize("NFC", s1)
    s2 = normalize("NFC", s2)
    print(s1, s2)    # café café
    print(s1 == s2)  # True
    print(s1.encode('utf8'), s2.encode('utf8'))   # b'cafxc3xa9' b'cafxc3xa9'

    # "NFKC"&"NFKD"
    # 这两种方式会损失信息,所以不建议使用,除非一些特殊情况,比如搜索和索引中
    s3 = '½'
    print(normalize('NFKC', s3))    # 1⁄2    将½转换成了1⁄2
    s4 = '™'
    print(normalize('NFKC', s4))    # TM     将™转换成了TM
    '''
    另外,如果比较的时候不区分大小写,建议使用str.casefold(), 它与lower基本一致,其中大约有116个特殊的字符结果不同
    '''
    s5 = 'AKJkakshfKHDSdshfKSDShKkHkjhKJkgJhgJHkkHkjhJKhKJhK'
    print(s5.casefold())    # akjkakshfkhdsdshfksdshkkhkjhkjkgjhgjhkkhkjhjkhkjhk

 

python高档系列作品目录

python高级——目录

 

文本和字节体系(编码难题),python字节 本文首要内容 字符 字节 结构体和内部存款和储蓄器视图 字符和字节之间的转变——编解...

为了科学比较而规范化Unicode字符串。

因为Unicode有结合字符。四个单词也会有三种办法组成,分别会有4个只怕5码位。然则结果是一心平等的,在python中,因为看到的是见仁见智的码位系列,因而肯定双方不对等。
缓和那个难题得以采用unicodedata.normalize函数提供的Unicode规范化。

  • NFC :使用最少的码位构成等价的字符串
  • NFD :把组合字符分解成基字符和独立的咬合字符。
  • NFKC : 兼容形式
  • NFKD :包容方式
    地点的二种包容形式标准化形式只能在卓绝情状下利用,比方找出和目录。不能用于长久存款和储蓄。
>>> s = 'café'
>>> len(s)
4
>>> b = s.encode('utf-8')
>>> b
b'cafxc3xa9'
>>> len(b)
5
>>> b.decode('utf-8')
'café'

Unicode文本排序

'''
    python比较序列时,会一一比较其中的元素。对于字符来说,比较的是其码位,主要是比较的ascii码;
    非ascii文本的标准排序方式是使用locale.strxfrm函数,但是使用这个函数必须事先设定区域,但有些操作系统不支持,并且改变区域设置并不十分合适

    建议使用pyuca.Collator.sort_key方法进行排序
'''



if __name__ == "__main__":
    # python默认的排序
    fruits = ['caju', 'atemoia', 'cajá', 'açaí', 'acerola']
    print(sorted(fruits))    # ['acerola', 'atemoia', 'açaí', 'caju', 'cajá']

                            # 但正确排序应该是:['açaí','acerola', 'atemoia', 'cajá', 'caju']

    # 使用pyuca.Collator.sort_key

    import pyuca
    print(sorted(fruits, key = pyuca.Collator().sort_key))   # ['açaí', 'acerola', 'atemoia', 'cajá', 'caju']

    # pyuca可以将自定义排序表路径传递给Collator()构造方法,pyuca默认使用自带的allkeys.txt

 

大大小小折叠

大大小小写折叠其实便是把富有文件转为小写,再做些其它转变。那么些效果由str.casefold()方法帮衬。

  假使想帮助和睦记住 .decode() 和 .encode() 的不相同,能够把字节类别想成晦涩难懂的机器磁芯转储,把 Unicode 字符串想成“人类可读”的公文。那么,把字节系列形成年人类可读的文本字符串正是解码,而把字符串形成用于存储或传输的字节连串正是编码。

python高等连串小说目录

python高级——目录

 

去掉变音符合

思路:

  • 选择NFD标准化unicode字符。分解为基字符和整合暗号
  • 过滤全体结成记号
  • 整合全部字符

 

Unicode文本排序

能够选用PyUCA库。

字节概要

Unicode 数据库

Unicode标准提供了二个完好的数据库,不独有包含码位与字符名称之间的炫彩,还应该有各样字符的元数据,以及字符之间的关系。

  • unicodedate.name()
  • unicodedata.numeric()
  • .isdecimal():
  • .isnumeic():

  新的二进制系列类型在非常多方面与 Python 2 的 str 类型不一样。首先要清楚,Python 内置了二种为主的二进制类别类型:Python 3 引进的不行变bytes 类型和 Python 2.6 添加的可变 bytearray 类型。(Python 2.6 也引入了 bytes 类型,但那只可是是 str 类型的别称,与 Python 3 的bytes 类型不相同。)

扶助字符串和字节连串的双格局API

re和os模块

  bytes 或 bytearray 对象的各种要素是介于 0~255(含)之间的卡尺头,而不像 Python 2 的 str 对象那样是单个的字符。可是,二进制系列的切成丝始终是一致类型的二进制系列,包涵长度为 1 的切条,如示例:

>>> cafe = bytes('café', encoding='utf_8')
>>> cafe
b'cafxc3xa9'
>>> cafe[0]
99
>>> cafe[:1]
b'c'
>>> cafe_arr = bytearray(cafe)
>>> cafe_arr
bytearray(b'cafxc3xa9')
>>> cafe_arr[-1:]
bytearray(b'xa9')

二进制类别有个类措施是 str 未有的,名叫fromhex,它的成效是深入分析十六进制数字对(数字对中间的空格是可选的),创设二进制系列:

>>> bytes.fromhex('31 4B CE A9')
b'1Kxcexa9'
>>> bytes.fromhex('31 4B CE A9').decode('utf-8')
'1KΩ'

采用数组中的原始数据初叶化 bytes 对象

>>> import array
>>> numbers = array.array('h', [-2, -1, 0, 1, 2])
>>> octets = bytes(numbers)
>>> octets
b'xfexffxffxffx00x00x01x00x02x00'

 

结构体和内部存款和储蓄器视图 

  struct 模块提供了一部分函数,把包裹的字节系列转变到分化等级次序字段组成的元组,还大概有部分函数用于施行反向转变,把元组转换来打包的字节体系。struct 模块能管理 bytes、bytearray 和 memoryview 对象。

采用memoryview 和 struct 查看贰个 GIF 图像的首部

>>> import struct
>>> fmt = '<3s3sHH' # ➊
>>> with open('filter.gif', 'rb') as fp:
... img = memoryview(fp.read()) # ➋
...
>>> header = img[:10] # ➌
>>> bytes(header) # ➍
b'GIF89a x02xe6x00'
>>> struct.unpack(fmt, header) # ➎
(b'GIF', b'89a', 555, 230)
>>> del header # ➏
>>> del img
  1. 结构体的格式:< 是小字节序,3s3s 是三个 3 字节种类,HH 是八个16 位二进制整数
  2. 接纳内部存款和储蓄器中的公文内容成立三个memoryview对象
  3. 然后选取它的切条在开创二个memoryview对象,这里不会复制字节类别
  4. 转换来字节连串,这里只是为着显得,这里复制了是个字节
  5. 拆包memoryview对象,获得二个元祖,包蕴类型、版本、宽度和可观
  6. 删除援用,释放memoryview实例所吞没的内部存储器

 

处理UnicodeEncodeError

  大多非 UTF 编解码器只好管理 Unicode 字符的一小部分子集。把文件调换来字节种类时,假诺目的编码中尚无概念某些字符,那就能够抛出UnicodeEncodeError 十分,除非把 errors 参数字传送给编码方法或函数,对不当进行出格管理。

举个  编码成字节种类:成功和错误管理

 1 city = 'São Paulo'
 2 
 3 #'utf_?' 编码能处理任何字符串
 4 u8 = city.encode('utf_8')
 5 print('utf-8:', u8)
 6 
 7 u16 = city.encode('utf_16')
 8 print('utf-16:', u16)
 9 
10 #'iso8859_1' 编码也能处理字符串 'São Paulo
11 iso = city.encode('iso8859_1')
12 print('iso:', iso)
13 
14 #报错咯,'cp437' 无法编码 'ã'(带波形符的“a”)
15 #city.encode('cp437')
16 
17 #解决方法如下
18 cp_ig = city.encode('cp437', errors='ignore')
19 print('cp ignore:', cp_ig)
20 
21 cp_rp = city.encode('cp437', errors='replace')
22 print('cp replace:', cp_rp)

上述代码试行的结果为:

utf-8: b'Sxc3xa3o Paulo'
utf-16: b'xffxfeSx00xe3x00ox00 x00Px00ax00ux00lx00ox00'
iso: b'Sxe3o Paulo'
cp ignore: b'So Paulo'
cp replace: b'S?o Paulo'

注意:

  1. error='ignore' 管理格局不知不觉地跳过不或许编码的字符;那样做通常极度不妥
  2. 编码时钦定error='replace',把不恐怕编码的字符替换到'?';数据损坏了,可是用户知道出现了难点

 

处理公事文件 

  管理文件的特级实施是“Unicode 大理治”(如图下图所示)。 意思是,要赶紧把输入(举个例子读取文件时)的字节系列解码成字符串。这种东营治中的“肉片”是先后的事情逻辑,在那边只可以管理字符串对象。在别的管理进度中,一定不能够编码或解码。对出口来讲,则要硬着头皮晚地把字符串编码成字节类别。许多Web 框架都以那般做的,使用框架时非常少接触字节体系。举个例子,在 Django 中,视图应该出口 Unicode 字符串;Django 会担负把响应编码成字节连串,而且暗中同意使用 UTF-8 编码。

澳门新萄京官方网站 5

拍卖文件文件一点也不细略。不过,假设借助私下认可编码,你会遇上麻烦。举个

 1 #打开一个文件cafe.txt并写入内容,w是对文件的模式操作(写操作), encoding是对文件操作的编码
 2 fp = open('cafe.txt', 'w', encoding='utf_8')
 3 fp_len = fp.write('café')
 4 print('fp的io信息:', fp)
 5 print('写入到文件中内容的长度:', fp_len)
 6 fp.close()
 7 
 8 #获取文件的内容
 9 fp2 = open('cafe.txt')
10 print('fp2的io信息:', fp2)
11 '''
12 因为和上面的写入的编码不同,所以直接以默认的编码打开,无法处理é而引发异常
13 '''
14 #print(fp2.read())
15 fp2.close()
16 
17 #解决fp2无法或许文件内容的方法指定打开的时候编码
18 fp3 = open('cafe.txt', encoding='utf-8')
19 print('fp3的io信息:', fp3)
20 print('fp3中的文件内容:', fp3.read())
21 fp3.close()
22 
23 fp4 = open('cafe.txt', 'rb')
24 print('fp4的io信息:', fp4)
25 print('fp4的文件内容:', fp4.read().decode('utf-8'))
26 fp4.close()
27 
28 #另外一种不太可取的解决方案, errors可以设置成replace或者ignore
29 fp5 = open('cafe.txt', 'r', errors='ignore')
30 print('fp5的io信息:', fp5)
31 print('fp5的文件内容:', fp5.read())

上述代码实践的结果为:

fp的io信息: <_io.TextIOWrapper name='cafe.txt' mode='w' encoding='utf_8'>
写入到文件中内容的长度: 4
fp2的io信息: <_io.TextIOWrapper name='cafe.txt' mode='r' encoding='US-ASCII'>
fp3的io信息: <_io.TextIOWrapper name='cafe.txt' mode='r' encoding='utf-8'>
fp3中的文件内容: café
fp4的io信息: <_io.BufferedReader name='cafe.txt'>
fp4的文件内容: café
fp5的io信息: <_io.TextIOWrapper name='cafe.txt' mode='r' encoding='US-ASCII'>
fp5的文件内容: caf

研讨编码私下认可值

 1 import  sys, locale
 2 
 3 
 4 expressions = """
 5     locale.getpreferredencoding()       
 6     type(my_file)                       
 7     my_file.encoding                    
 8     sys.stdout.isatty()                 
 9     sys.stdout.encoding                 
10     sys.stdin.isatty()                  
11     sys.stdin.encoding
12     sys.stderr.isatty()
13     sys.stderr.encoding
14     sys.getdefaultencoding()
15     sys.getfilesystemencoding()
16 """
17 
18 with open('dummy', 'w') as my_file:
19     for expression in expressions.split():
20         value = eval(expression)
21         print('{:>30}'.format(expression), '->', repr(value))
22         
23 '''
24 locale.getpreferredencoding() 是最重要的设置
25 文本文件默认使用 locale.getpreferredencoding()
26 输出到控制台中,因此 sys.stdout.isatty() 返回 True
27 因此,sys.stdout.encoding 与控制台的编码相同
28 '''

以上代码施行的结果为(终端运转):

ocale.getpreferredencoding() -> 'UTF-8'
                 type(my_file) -> <class '_io.TextIOWrapper'>
              my_file.encoding -> 'UTF-8'
           sys.stdout.isatty() -> True
           sys.stdout.encoding -> 'UTF-8'
            sys.stdin.isatty() -> True
            sys.stdin.encoding -> 'UTF-8'
           sys.stderr.isatty() -> True
           sys.stderr.encoding -> 'UTF-8'
      sys.getdefaultencoding() -> 'utf-8'
   sys.getfilesystemencoding() -> 'utf-8'

 

为了科学相比较而标准化Unicode字符串

  因为 Unicode 有结合字符(变音符号和叠合到前一个字符上的符号,打字与印刷时作为一个完好),所以字符串比较起来很复杂。

  比如,“café”这个词能够接纳三种情势组成,分别有 4 个和 5 个码位,然而结果完全等同:

>>> s1 = 'café'
>>> s2 = 'cafeu0301'
>>> s1, s2
('café', 'café')
>>> len(s1), len(s2)
(4, 5)
>>> s1 == s2
False 

  'é' 和 'eu0301' 那样的行列叫“标准等价物”(佳能ical equivalent),应用程序应该把它们作为一样的字符。可是,Python 看到的是例外的码位体系,由此断定双方不等于。

     解决方案是选拔unicodedata.normalize 函数提供的Unicode 标准化。那些函数的第一个参数是这4 个字符串中的二个:'NFC'、'NFD'、'NFKC' 和 'NFKD'。下边先证实前多少个。

  NFC(Normalization Form C)使用最少的码位构成等价的字符串,而NFD 把组合字符分解成基字符和独门的结合字符。那三种规范化方式都能让相比行为符合预期:

 1 from unicodedata import normalize
 2 
 3 
 4 s1 = 'café' # 把"e"和重音符组合在一起
 5 s2 = 'cafeu0301' # 分解成"e"和重音符
 6 print('s1和s2的长度:', len(s1), len(s2))
 7 
 8 print('NFC标准化处理以后的s1,s2的长度:', len(normalize('NFC', s1)), len(normalize('NFC', s2)))
 9 print('NFD标准化处理以后的s1,s2的长度:', len(normalize('NFD', s1)), len(normalize('NFD', s2)))
10 print(normalize('NFC', s1), normalize('NFC', s2))

如上代码试行的结果为:

s1和s2的长度: 4 5
NFC标准化处理以后的s1,s2的长度: 4 4
NFD标准化处理以后的s1,s2的长度: 5 5
café café

  在别的五个标准化格局(NFKC 和 NFKD)的首字母缩略词中,字母 K表示“compatibility”(包容性)。这二种是较严厉的标准化格局,对“兼容字符”有震慑。即使Unicode 的靶子是为顺序字符提供“标准的”码位,然则为了合作现有的业内,某个字符会出现每每。例如,尽管希腊共和国(Ελληνική Δημοκρατία)字母表中有“μ”这些字母(码位是 U 03BC,GREEK SMALL LETTE奥迪Q3 MU),可是 Unicode 如故参预了微符号 'μ'(U 00B5),以便与 latin1 互相调换。由此,微符号是三个“包容字符”。

NFC的现实性应用

>>> from unicodedata import normalize
>>> half = '½'
>>> normalize('NFKC', half)
'1⁄2'
>>> four_squared = '4²'
>>> normalize('NFKC', four_squared)
'42'
>>> micro = 'μ'
>>> micro_kc = normalize('NFKC', micro)
>>> micro, micro_kc
('μ', 'μ')
>>> ord(micro), ord(micro_kc)
(956, 956)

  使用 '57%' 代替 '½' 能够承受,微符号也的确是小写的希腊语(Greece)字母'μ',不过把 '4²' 转变来 '42' 就改成原意了。某个应用程序能够把'4²' 保存为 '4<sup>2</sup>',不过 normalize 函数对格式一窍不通。因而,NFKC 或 NFKD 恐怕会损失或篡改新闻,但是足认为搜索和目录提供方便的中游表述:用户搜索'1 / 2 inch' 时,假诺还是可以找到富含 '½ inch' 的文书档案,那么用户会倍感满足。

注意:

  使用 NFKC 和 NFKD 规范化情势时要当心,并且不得不在至极意况中运用,比方搜索和目录,而无法用来长久存款和储蓄,因为那二种转移会促成数据损失。

 

规范化文本匹配实用函数

  由前文可知,NFC 和 NFD 能够放心使用,并且能合理相比 Unicode 字符串。对大多数应用来讲,NFC 是最棒的标准化方式。不区分轻重缓急写的可比应该选用 str.casefold()。

  即使要拍卖多语言文本,工具箱中采用nfc_equal 和fold_equal 函数。

  相比较标准化 Unicode 字符串

 1 from unicodedata import normalize
 2 
 3 
 4 def nfc_equal(str1, str2):
 5     return normalize('NFC', str1) == normalize('NFC', str2)
 6 
 7 def fold_equal(str1, str2):
 8     return (normalize('NFC', str1).casefold() ==
 9             normalize('NFC', str2).casefold())
10 
11 s1 = 'café'
12 s2 = 'cafeu0301'
13 print('s1 equal s2:',nfc_equal(s1, s2))
14 
15 print(nfc_equal('A', 'a'))
16 
17 s3 = 'Straße'
18 s4 = 'strasse'
19 
20 print('s3 equal s4', nfc_equal(s3, s4))
21 #转换字符成小写
22 print(fold_equal(s3, s4)) 

如上代码的实践结果为:

s1 equal s2: True
False
s3 equal s4 False
True

最佳“标准化”:去掉变音符号

去掉变音符号仍可以让 U瑞虎L 更便于阅读,至少对拉丁语系语言是如此。上面是维基百科中介绍洛杉矶市(São Paulo)的小说的U锐界L:

http://en.wikipedia.org/wiki/São_Paulo

个中,“ã”是 UTF-8 编码“ã”字母(带有波形符的“a”)转义后获取的结果。下述方式更融洽,固然拼写是大错特错的:

http://en.wikipedia.org/wiki/Sao_Paulo

假设想把字符串中的全数变音符号都去掉,看 

 1 import unicodedata
 2 
 3 
 4 def shave_marks(txt):
 5     """去掉全部变音符号"""
 6 
 7     norm_txt = unicodedata.normalize('NFD', txt)        #把所有字符分解成基字符和组合记号
 8     shaved = ''.join(c for c in norm_txt
 9                      if not unicodedata.combining(c))   #过滤掉所有组合记号
10     return unicodedata.normalize('NFC', shaved)         #重组所有字符
11 
12 
13 order = '“Herr Voß: • ½ cup of OEtker™ caffè latte • bowl of açaí.”'
14 print(shave_marks(order))
15 
16 Greek = 'Zέφupoς, Zéfiro'
17 print(shave_marks(Greek))

以上代码推行的结果为:

“Herr Voß: • ½ cup of OEtker™ caffe latte • bowl of acai.”
Zεφupoς, Zefiro

 

Unicode文本排序

  Python 相比任何项目标行列时,会挨个比较连串里的顺序要素。对字符串来讲,相比较的是码位。不过在可比非 ASCII 字符时,获得的结果不顺遂。

本文由澳门新萄京官方网站发布于www.8455.com,转载请注明出处:文本和字节序列,编码格式

关键词: