VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • Python3标准库:codecs字符串编码和解码

1. codecs字符串编码和解码

codecs模块提供了流接口和文件接口来完成文本数据不同表示之间的转换。通常用于处理Unicode文本,不过也提供了其他编码来满足其他用途。

1.1 Unicode入门

CPython 3.x区分了文本(text)和字节(byte)串。bytes实例使用一个8位字节值序列。与之不同,str串在内部作为一个Unicode码点(code point)序列来管理。码点值使用2字节或4字节表示,这取决于编译Python时指定的选项。 

输出str值时,会使用某种标准机制编码,以后可以将这个字节序列重构为同样的文本串。编码值的字节不一定与码点值完全相同,编码只是定义了两个值集之间转换的一种方式。读取Unicode数据时还需要知道编码,这样才能把接收到的字节转换为unicode类使用的内部表示。

西方语言最常用的编码是UTF-8和UTF-16,这两种编码分别使用单字节和两字节值序列表示各个码点。对于其他语言,由于大多数字符都由超过两字节的码点表示,所以使用其他编码来存储可能更为高效。

要了解编码,最好的方法就是采用不同方法对相同的串进行编码,并查看所生成的不同的字节序列。下面的例子使用以下函数格式化字节串,使之更易读。


	
  1. import binascii
  2.  
  3. def to_hex(t, nbytes):
  4. """Format text t as a sequence of nbyte long values
  5. separated by spaces.
  6. """
  7. chars_per_item = nbytes * 2
  8. hex_version = binascii.hexlify(t)
  9. return b' '.join(
  10. hex_version[start:start + chars_per_item]
  11. for start in range(0, len(hex_version), chars_per_item)
  12. )
  13.  
  14. if __name__ == '__main__':
  15. print(to_hex(b'abcdef', 1))
  16. print(to_hex(b'abcdef', 2))

这个函数使用binascii得到输入字节串的十六进制表示,在返回这个值之前每隔nbytes字节就插入一个空格。

第一个编码示例首先使用unicode类的原始表示来打印文本'francais',后面是Unicode数据库中各个字符的名。接下来两行将这个字符串分别编码为UTF-8和UTF-16,并显示编码得到的十六进制值。


	
  1. import unicodedata
  2. import binascii
  3.  
  4. def to_hex(t, nbytes):
  5. """Format text t as a sequence of nbyte long values
  6. separated by spaces.
  7. """
  8. chars_per_item = nbytes * 2
  9. hex_version = binascii.hexlify(t)
  10. return b' '.join(
  11. hex_version[start:start + chars_per_item]
  12. for start in range(0, len(hex_version), chars_per_item)
  13. )
  14.  
  15. text = 'français'
  16.  
  17. print('Raw : {!r}'.format(text))
  18. for c in text:
  19. print(' {!r}: {}'.format(c, unicodedata.name(c, c)))
  20. print('UTF-8 : {!r}'.format(to_hex(text.encode('utf-8'), 1)))
  21. print('UTF-16: {!r}'.format(to_hex(text.encode('utf-16'), 2)))

对一个str编码的结果是一个bytes对象。

给定一个编码字节序列(作为一个bytes实例),decode()方法将其转换为码点,并作为一个str实例返回这个序列。 


	
  1. import binascii
  2.  
  3. def to_hex(t, nbytes):
  4. """Format text t as a sequence of nbyte long values
  5. separated by spaces.
  6. """
  7. chars_per_item = nbytes * 2
  8. hex_version = binascii.hexlify(t)
  9. return b' '.join(
  10. hex_version[start:start + chars_per_item]
  11. for start in range(0, len(hex_version), chars_per_item)
  12. )
  13.  
  14. text = 'français'
  15. encoded = text.encode('utf-8')
  16. decoded = encoded.decode('utf-8')
  17.  
  18. print('Original :', repr(text))
  19. print('Encoded :', to_hex(encoded, 1), type(encoded))
  20. print('Decoded :', repr(decoded), type(decoded))

选择使用哪一种编码不会改变输出类型。

1.2 处理文件

处理I/O操作时,编码和解码字符串尤其重要。不论是写至一个文件、套接字还是其他流,数据都必须使用适当的编码。一般来讲,所有文本数据在读取时都需要由其字节表示解码,写数据时则需要从内部值编码为一种特定的表示。程序可以显式的编码和解码数据,不过取决于所用的编码,要想确定是否已经读取足够的字节来充分解码数据,这可能并不容易。codecs提供了一些类来管理数据编码和解码,所以应用不再需要做这个工作。

codecs提供的最简单的接口可以替代内置open()函数。这个新版本的函数与内置函数的做法很相似,不过增加了两个参数来指定编码和所需的错误处理技术。 


	
  1. import binascii
  2. import codecs
  3.  
  4. def to_hex(t, nbytes):
  5. """Format text t as a sequence of nbyte long values
  6. separated by spaces.
  7. """
  8. chars_per_item = nbytes * 2
  9. hex_version = binascii.hexlify(t)
  10. return b' '.join(
  11. hex_version[start:start + chars_per_item]
  12. for start in range