Python 3最重要的新特性之一是对字符串和二进制数据流做了明确的区分。文本总是Unicode
,由str
类型表示,二进制数据则由bytes
类型表示。
这里理解:
str类型是Python的一种数据类型,当你需要使用其他库或与其它程序联用时,往往需要使用二进制数进行信息传递。
除了本文要介绍的hashlib外,如果没有使用二进制数进行信息传递,当你在写网页返回值时,也会报错,如
def run_server(environ):
# 返回的内容
# return ['<h1>hello, show a web</h1>',] # 这样会报错
return ['<h1>hello, show a web</h1>'.encode('utf-8'),]
好,我们开始从hashlib入手
hashlib 简介:Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等,它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
import hashlib
def test_hashlib():
md5obj = hashlib.md5()
md5obj.update('this is a string')
rst = md5obj.hexdigest()
print(rst) # 9912912bd6c6d2a257cbcf8430f6fc61
TypeError: Unicode-objects must be encoded before hashing
如果你像上面这么写,会直接报错:
TypeError: Unicode-objects must be encoded before hashing
原因在于hashlib的方法update只接收字节编码类型
那么,我们可以通过以下3中方式进行编码,解决问题:
def test_hashlib():
md5obj = hashlib.md5()
md5obj.update(b'this is a string') # 方法一
# md5obj.update('this is a string.'.encode('utf-8')) # 方法二
# md5obj.update(bytes('this is a string.', encoding='utf-8')) # 方法三
rst = md5obj.hexdigest()
print(rst) # 9912912bd6c6d2a257cbcf8430f6fc61
但考虑到我的系统环境编码为 utf-8,那么在方法二的基础上可以这么写:
def test_hashlib():
md5obj = hashlib.md5()
md5obj.update(b'this is a string') # 方法一
# md5obj.update('this is a string.'.encode('utf-8')) # 方法二
# md5obj.update('this is a string.'.encode()) # 方法四
# md5obj.update(bytes('this is a string.', encoding='utf-8')) # 方法三
rst = md5obj.hexdigest()
print(rst) # 9912912bd6c6d2a257cbcf8430f6fc61
可以理解为,你在编译器输入的字符串 'this is a string',这是使用utf-8编码的Python内置str型数据,而hashlib不认识str型数据,它只接收字节流,那么我们就要把utf-8 编码的 'this is a string' 字符串编码为字节流,而系统默认是utf-8编码,你可以不指名用什么进行编码。
当然,为了测试,我们可以把系统默认的utf-8编码的字符串,转为gbk字符串,然后再转为字符型
为方法五
def test_hashlib():
md5obj = hashlib.md5()
md5obj.update(b'this is a string') # 方法一
# md5obj.update('this is a string.'.encode('utf-8')) # 方法二
# md5obj.update('this is a string.'.encode()) # 方法四
# md5obj.update(bytes('this is a string.', encoding='utf-8')) # 方法三
# md5obj.update('this is a string.'.encode('utf-8').decode('gbk').encode('gbk')) # 方法五
# md5obj.update('this is a string.'.encode('').decode('gbk').encode('gbk').decode().encode()) # 方法六
rst = md5obj.hexdigest()
print(rst) # 9912912bd6c6d2a257cbcf8430f6fc61
方法六可以理解为再把二进制数据(字节型)数据转为系统默认编码(utf-8),然后再转为字节型数据
总结:
所有编码类型转换,都需要先转为字节型,然后再转为你想要的编码
utf-8字符串 ------encode------> bytes类型 -----decode-----> 你想要的编码类型
希望对大家有帮助,如果有描述不清楚的地方请多多批评指正 ^^