python内置模块(三)

内置模块datetimetimecommands相关内容点击python内置模块查看。
内置模块subprocessosrandomsyslogging相关内容点击python内置模块(二)查看。

hashlib

haslib模块为不同的安全哈希/安全散列(Secure Hash Algorithm)和信息摘要算法(Message Digest Algorithm)实现了一个公共的、通用的接口。haslib模块提供了很多算法的函数实现,例如:md5、sha1、sha224、sha256、sha384、sha512等。

此处简单介绍下集中数据加密方式

数据加密方式 描述 主要解决问题 常用算法
对称加密 数据加密和解密使用相同的密钥 数据的机密性 DES,AES
非对称加密 也叫公钥加密,指数据加密和解密使用不同的密钥(密钥对) 身份验证 DSA,RSA
单向加密 只能加密数据,不能解密数据 数据的完整性验证 MD5,SHA系统算法

摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的字符串(通常用16进制字符串表示)。常用的是md5算法。
hashlib模块对应的属性和函数

  • hselib.new(name[, date])
    通用的哈希对象构造函数,用于构造指定的哈希算法对应的哈希对象。其中name用于指定哈希算法名称,如md5sha1,不区分大小写;data可选,表示初始数据。

    1
    2
    3
    >>> import hashlib
    >>> hashlib.new('md5') #构建hash对象
    <md5 HASH object @ 0x00000131AE948AD0>
  • hashlib.算法名称()
    可以直接通过具体的哈希算法名称对应的函数获取哈希对象,如hashlib.md5()等。
    hashlib.md5()和hashlib.new(‘md5’)是等价的。

    1
    2
    3
    >>> import hashlib
    >>> hashlib.md5()
    <md5 HASH object @ 0x00000131AE9489E0>
  • hashlib.algorithms_guaranteed
    它的值是该模块在所有平台都支持的哈希算法的名称集合。

    1
    2
    3
    >>> import hashlib
    >>> hashlib.algorithms_guaranteed
    {'sha384', 'blake2b', 'sha3_384', 'shake_128', 'sha3_256', 'sha3_224', 'md5', 'sha3_512', 'blake2s', 'sha224', 'shake_256', 'sha256', 'sha512', 'sha1'}
  • hashlib.algorithms_available
    当前运行python解释器中可用的哈希算法的集合。algorithms_guaranteed是它的子集。

    1
    2
    3
    >>> import hashlib
    >>> hashlib.algorithms_available
    {'md4', 'sha3_384', 'shake_128', 'whirlpool', 'SHA224', 'blake2s', 'ripemd160', 'MD4', 'sha1', 'sha384', 'SHA384', 'ecdsa-with-SHA1', 'md5', 'SHA256', 'DSA-SHA', 'SHA1', 'sha3_512', 'shake_256', 'sha', 'sha256', 'sha512', 'DSA', 'RIPEMD160', 'blake2b', 'dsaEncryption', 'SHA512', 'sha3_224', 'sha224', 'SHA', 'sha3_256', 'MD5', 'dsaWithSHA'}

hash对象对应的属性和方法

  • hash.update()
    更新哈希对象所要计算的数据,多次调用为累加效果。
    m.update(a);m.update(b)等价于m.update(a+b)
  • hash.digest()
    返回传递给update()函数的所有数据的摘要信息(二进制格式的字符串)
  • hash.hexdigest()
    返回传递给update()函数的所有数据的摘要信息(十六进制格式的字符串)
  • hash.copy()
    返回该哈希对象的一个copy(“clone”),这个函数可以用来有效的计算共享一个公共初始化子串的数据的摘要信息。
  • hash.digest_size
    hash结果的字节大小,即hash.digest()方法返回结果的字符串长度。该值对于哈希对象是固定的。md5:16,sha1:20, sha224:28。
  • hash.name
    当前哈希对象对应的哈希算法的标准名称(小写),可以直接传递给hashlib.new()函数来创建另外一个同类型的哈希对象。
    使用示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    >>> import hashlib
    >>> m = hashlib.md5() #创建hash对象
    >>> m.update('hello world'.encode('utf-8')) #更新hash对象的计算数据
    >>> print(m)
    <md5 HASH object @ 0x00000131AE9489E0>
    >>> print(m.hexdigest()) #返回对应数据摘要信息(十六进制)
    5eb63bbbe01eeed093cb22bb8f5acdc3
    >>> print(m.digest()) #返回对应数据摘要信息(二进制)
    b'^\xb6;\xbb\xe0\x1e\xee\xd0\x93\xcb"\xbb\x8fZ\xcd\xc3'
    >>> print(m.name) #返回使用的哈希算法
    md5
    >>> print(m.digest_size) #返回字符串长度
    16

注意点:

  1. 实际使用中都是获取十六进制的字符串,也就是使用hash.hexdigest()
  2. 使用hashlib模块一般是3步,通过hashlib.md5()创建哈希对象;通过update()追加需要计算的数据;通过hexdigest()得到数据对应的十六进制字符串(也就是摘要信息)。

    StringIO

    StringIO主要用来在内存中写入字符串及字符串的缓存。其接口和文件操作的接口是一致的,基本所有关于文件的方法都可以用。
    关于文件操作的方法可以点击python文件操作查看更多内容。
    示例
    1
    2
    3
    4
    5
    6
    >>> from io import StringIO
    >>> s = StringIO() #初始化StringIO对象
    >>> s.write('hello world') #写入字符串
    11
    >>> s.getvalue() #获取实例中的字符串
    'hello world'

stringIO.getvalue()返回StringIO实例中的字符串。
读取StringIO中的字符串,也可以使用文件类似的readreadlinereadlines等方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> s = StringIO()
>>> s.write('hello world')
11
>>> s.write('\n new line')
10
>>> s.seek(0) #回到文件开头
0
>>> for line in s:
... print(line)
...
hello world

new line

BytesIO

StringIO操作只能是str,如果要操作二进制数据,就需要使用BytesIO
BytesIO实现了在内存中读写bytes。

1
2
3
4
5
6
7
8
9
10
11
12
>>> from io import BytesIO
>>> f = BytesIO()
>>> f.write('中文'.encode('utf-8'))
6
>>> print(f.getvalue())
b'\xe4\xb8\xad\xe6\x96\x87'
>>> f.seek(0) #回到文件最开头
0
>>> f.read() #读取
b'\xe4\xb8\xad\xe6\x96\x87'
>>> '中文'.encode('utf-8') #读取的内容和写入的对比
b'\xe4\xb8\xad\xe6\x96\x87'

此处写入的内容不是中文字符串,而是经过UTF-8编码的bytes。

Json

Json(JavaScript Object Notation),它是一种轻量级的数据交换格式。其应用最广泛的是作为AJAX中web服务器和客户端的通讯的数据格式,现在也常用于http请求。

  • 序列化和反序列化
    将对象转换为可通过网络传输或可以存储到本地磁盘的数据格式(如:XML、JSON或特定数据格式)的过程称为序列化;反之则称为反序列化。
    python的JSON模块序列化和反序列化的过程分别叫做:encoding和decoding。
    encoding:把python对象转换成JSON字符串。
    decoding:把JSON字符串转换成python对象。
    json模块提供了下面的方法进行序列化和反序列化操作
    1
    2
    3
    4
    #序列化:将python对象转换成json字符串
    dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
    #反序列化:将json字符串转换成python对象
    loads(s, *, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

将序列化后得到的json数据保存到文件以及直接读取文件中的json数据进行反序列化操作

1
2
3
4
#序列化:将python对象转换成json字符串并存储到文件
dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
#反序列化:读取指定文件中的json字符串并转换成python对象
load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

json和python数据类型对应关系

  1. python转换为json
Python JSON
dict object
list,tuple array
str string
int,float,int- & float-derived Enums number
True true
False false
None null
  1. json转换为python
JSON Python
object dict
array list
string str
number(int) int
number(real) float
true True
false False
null None

序列化示例

1
2
3
>>> import json
>>> json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)})
'{"a": "str", "c": true, "e": 10, "b": 11.1, "d": null, "f": [1, 2, 3], "g": [4, 5, 6]}'

sort_keys参数: 表示序列化时是否对dict的key进行排序(dict默认是无序的)

1
2
>>> json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}, sort_keys=True)
'{"a": "str", "b": 11.1, "c": true, "d": null, "e": 10, "f": [1, 2, 3], "g": [4, 5, 6]}'

indent参数: 表示缩进,它可以使得数据存储的格式变得更加优雅、可读性更强;如果indent是一个非负整数或字符串,则JSON array元素和object成员将会被以相应的缩进级别进行打印输出;如果indent是0或负数或空字符串,则将只会插入换行,不会有缩进。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> print(json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}, sort_keys=True, indent=4))
{
"a": "str",
"b": 11.1,
"c": true,
"d": null,
"e": 10,
"f": [
1,
2,
3
],
"g": [
4,
5,
6
]
}

separators参数: 尽管indent参数可以使得数据存储的格式变得更加优雅、可读性更强,但是那是通过添加一些冗余的空白字符进行填充的。当json被用于网络数据通信时,应该尽可能的减少无用的数据传输,这样可以节省带宽并加快数据传输速度。json模块序列化Python对象后得到的json字符串中的’,’号和’:’号分隔符后默认都会附加一个空白字符,我们可以通过separators参数重新指定分隔符,从而去除无用的空白字符。
该参数的值应该是一个tuple(item_separator, key_separator)

  • 若indent是None,其默认值为(‘, ‘, ‘: ‘)
  • 若indent不为None,则默认值为(‘,’, ‘: ‘)
  • 我们可以通过为separator赋值为(‘,’, ‘:’)来消除空白字符
    1
    2
    3
    4
    >>> json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)})
    '{"a": "str", "c": true, "e": 10, "b": 11.1, "d": null, "f": [1, 2, 3], "g": [4, 5, 6]}'
    >>> json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}, separators=(',',':'))
    '{"a":"str","c":true,"e":10,"b":11.1,"d":null,"f":[1,2,3],"g":[4,5,6]}'

ensure_ascii参数: 当该参数的值为True(默认值)时,输出中的所有非ASCII字符(比如中文)都会被转义成’\uXXXX’组成的序列,得到的结果是一个完全由ASCII字符组成的str实例。如果我们想得到一个人类可读的输出结果,需要把ensure_ascii参数的值设置为False。

1
2
3
4
5
6
7
>>> stu={"name": "小明", "age" : 16}
>>> stu_json = json.dumps(stu)
>>> print(stu_json)
{"name": "\u5c0f\u660e", "age": 16}
>>> stu_json01 = json.dumps(stu, ensure_ascii=False)
>>> print(stu_json01)
{"name": "小明", "age": 16}

说明:\u5c0f\u660e是unicode字符对应的内存编码值,该内存编码名称为”unicode-escape”。可以通过unicodestr.encode('unicode-escape')decode('unicode-escape')完成unicode字符串和Unicode内存编码序列进行相互转换。
反序列化示例

1
2
3
4
>>> json.loads('{"a": "str", "c": true, "b": 11.1, "e": 10, "d": null, "g": [4, 5, 6], "f": [1, 2, 3]}')
{'a': 'str', 'c': True, 'b': 11.1, 'e': 10, 'd': None, 'g': [4, 5, 6], 'f': [1, 2, 3]}
>>> json.loads('{"a":"str","c":true,"b":11.1,"e":10,"d":null,"g":[4,5,6],"f":[1,2,3]}')
{'a': 'str', 'c': True, 'b': 11.1, 'e': 10, 'd': None, 'g': [4, 5, 6], 'f': [1, 2, 3]}

load()和dump()

1
2
3
4
5
6
7
8
9
#序列化到文件中
>>> with open('test.json', 'w') as fp:
... json.dump({'a':'str中国', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}, fp, indent=4)
...
#反序列化文件中的内容
>>> with open('test.json', 'r') as fp:
... json.load(fp)
...
{'a': 'str中国', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g': [4, 5, 6]}

注意:如果试图使用相同的fp调用dump()函数去序列化多个对象,将会产生一个无效的JSON文件。也就是说对于一个fd只能调用一次dump()
更多更详细的内容可以点击JSON encoder and decoder查看官网内容。

Recommended Posts