该模块以 uuencode
格式对文件进行编码和解码,允许通过仅使用 ascii
的连接传输任意二进制数据。该模块的编码和解码方法接受文件对象作为参数,但是也可以接受类似文件的对象作为参数。为了向后兼容,也接受包含路径名的字符串,并打开相应的文件进行读写;路径名 -
表示标准输入或输出。但是,该接口已经弃用;调用者最好打开文件本身,并确保在需要时,在Windows上使用 rb
或 wb
模式打开文件。
该模块包含如下两个主要方法:
uu.encode(in_file, out_file, name=None, mode=None, *, backtick=False)
将文件 in_file 的内容使用uuencode进行编码,然后将编码后的内容写入 out_file 文件。
name 参数用于指定 out_file 文件中起始行中的文件名字段,该文件名字段为重新构建二进制数据时要使用的文件名。如果未指定该参数,则 out_file 文件的起始行中的文件名默认为 in_file 的文件名。
mode 参数用于指定 out_file 文件中起始行中的模式字段。该参数最好指定为3位8进制数。如果未指定 mode 参数,则 out_file 文件中起始行中的模式字段的值默认为 644 。
backtick 参数决定是否使用反引号替换空格来表示新行。该参数值为默认值 False 时,使用空格表示新行,该参数为 True 时,使用反引号表示新行。
uu.decode(in_file, out_file, mode=None, quiet=False)
将 in_file 中uuencode编码的数据解码,并将解码的数据写入 out_file 文件。
如果 out_file 参数是表示文件路径的字符串,当 out_file 参数指向的文件必须被创建时, mode 参数用于设置 out_file 参数指向的文件的权限位。默认的 out_file 和 mode 从 in_file 的起始行中读取。如果起始行中指定的文件已经存在,则会引发 uu.Error 异常。
如果输入是由错误的uuencoder生成的,该方法可能会向标准错误输出警告,并且Python可以从错误中恢复。将 quiet 参数设置为 True 可以使此警告无效。
将文件进行uuencode编码:
>>> import uu
>>> with open('example.txt', 'w') as f:
f.writelines('this is an uuencode example.\ndo you understand the uuencode?')
>>> uu.encode('example.txt', 'uu_file.txt', 'uu.txt', 0o777, backtick=True)
>>> with open('uu_file.txt') as f:
... print(f.read())
...
begin 777 uu.txt
M=&AI<R!I<R!A;B!U=65N8V]D92!E>&%M<&QE+@ID;R!Y;W4@=6YD97)S=&%N
/9"!T:&4@=75E;F-O9&4_
`
end
解码uuencode编码的文件:
>>> uu.decode('uu_file.txt', 'text.txt')
>>> with open('text.txt') as f:
... print(f.read())
...
this is an uuencode example.
do you understand the uuencode?
此模块提供了将二进制数据编码为可打印的 ASCII 字符以及将这些编码解码回二进制数据的函数。它为 RFC 3548 指定的 Base16, Base32 和 Base64 编码以及已被广泛接受的 Ascii85 和 Base85 编码提供了编码和解码函数。
RFC 3548 编码的目的是使得二进制数据可以作为电子邮件的内容正确地发送,用作 URL 的一部分,或者作为 HTTP POST 请求的一部分。其中的编码算法和 uuencode 是不同的。
此模块提供了两个接口。新的接口提供了从类字节对象到 ASCII 字节 bytes
的编码,以及将 ASCII 的类字节对象 或字符串解码到 bytes
的操作。此模块支持定义在 RFC 3548 中的所有 base-64 字母表 (普通的、URL 安全的和文件系统安全的)。
旧的接口不提供从字符串的解码操作,但提供了操作文件对象的编码和解码函数。旧接口只支持标准的 Base64 字母表,并且按照 RFC 2045 的规范每 76 个字符增加一个换行符。注意:如果你需要支持 RFC 2045,那么使用 email 模块可能更加合适。
base64.b64encode(s, altchars=None)
将 bytes、bytearray 或 bytes-like 对象 s 编码成 bytes 对象。
若指定 altchars 参数,则必须为长度为2的 bytes-like 对象,用于替换Base64标准字母表中的 +
和 /
。
>>> base64.b64encode(b'talk is cheap, show me the code', b'-_')
b'dGFsayBpcyBjaGVhcCwgc2hvdyBtZSB0aGUgY29kZQ=='
base64.b64decode(s, altchars=None, validate=False)
解码Base64编码过的 bytes-like 对象 或ASCII 字符串 s 。
若指定 altchars 参数,则必须为长度为2的 bytes-like 对象,用于替换 +
和 /
字符。
如果 s 无法被解码,则会引发 binascii.Error 异常。
如果 validate 值为 False (默认情况),则在填充检查前,将丢弃既不在标准 Base64 字母表之中也不在备用字母表中的字符。如果 validate 为 True,这些非 Base64 字符将导致 binascii.Error 异常。
返回值为 bytes 对象。
>>> base64.b64decode(b'dGFsayBpcyBjaGVhcCwgc2hvdyBtZSB0aGUgY29kZQ==')
b'talk is cheap, show me the code'
>>> # bytes对象中包含非Base64字母表中的字符 “*”,并且validate为True时将引发异常
... base64.b64decode(b'dGFsayBpcyBjaGVhcCwgc2hvdyBtZSB0aGUgY29kZQ==*', validate=True)
Traceback (most recent call last):
File "" , line 2, in <module>
File "/Users/neochen/.virtualenvs/Test/lib/python3.7/base64.py", line 86, in b64decode
raise binascii.Error('Non-base64 digit found')
binascii.Error: Non-base64 digit found
>>> # bytes对象中包含非Base64字母表中的字符 “*”,并且validate为默认值False时,可以正常解码
... base64.b64decode(b'dGFsayBpcyBjaGVhcCwgc2hvdyBtZSB0aGUgY29kZQ==*')
b'talk is cheap, show me the code'
base64.standard_b64encode(s)
使用标准Base64字母表编码编码 bytes、bytearray 或 bytes-like 对象 s 。返回值为 bytes 对象。
base64.standard_b64decode(s)
使用标准Base64字母表解码 bytes-like 对象或 ASCII 字符串 s。返回值为 bytes 对象。
base64.urlsafe_b64encode(s)
将 bytes、bytearray 或 bytes-like 对象 s 编码成 bytes 对象。
使用URL安全和文件系统安全的字母表,即使用 -
和 _
替换 +
和 /
。
返回值为 bytes 对象。
base64.urlsafe_b64decode(s)
解码 bytes-like 对象或ASCII 字符串 s,使用URL安全和文件系统安全的字母表,即使用 -
和 _
替换 +
和 /
。
返回值为 bytes 对象。
base64.b32encode(s)
用Base32 编码 bytes-like 对象 s。返回值为 bytes 对象。
>>> base64.b32encode(b'talk is cheap, show me the code')
b'ORQWY2ZANFZSAY3IMVQXALBAONUG65ZANVSSA5DIMUQGG33EMU======'
base64.b32decode(s, casefold=False, map01=None)
解码Base32编码过的 bytes-like 对象或 ASCII 字符串 s。
若 casefold 的值为 False,则输入只能包含大写字母。若 casefold 的值为 True,则输入可以包含小写字母。
RFC 3548 允许将数字 0(zero) 映射为大写字母 O,并可以选择是否将数字 1(one) 映射为大写字母 I 或大写字母 L。可选参数 map01 不是 None 时, 数字 0 总是被映射为大写字母 O,map01 参数的值指定数字 1 的映射目标 (大写字母 I 或小写字母 l)。为了安全考虑,默认值被设为 None,这种情况下, 0 和 1 不允许被作为输入。
返回值为 bytes 类型。
>>> base64.b32decode(b'ORQWY2ZANFZSAY3IMVQXALBAONUG65ZANVSSA5DIMUQGG33EMU======')
b'talk is cheap, show me the code'
>>> # "casefold" 值为默认值 "False" 时,输入中不能包含小写字母
... base64.b32decode(b'ORQWY2ZANFZSAY3IMVQXALBAONUG65ZANVSSA5DIMUQGG33EMU======'.lower())
Traceback (most recent call last):
File "" , line 1, in <module>
File "/Users/neochen/.virtualenvs/Test/lib/python3.7/base64.py", line 231, in b32decode
raise binascii.Error('Non-base32 digit found') from None
binascii.Error: Non-base32 digit found
>>> # "casefold" 值为 "True" 时,输入可以包含小写字母
... base64.b32decode(b'ORQWY2ZANFZSAY3IMVQXALBAONUG65ZANVSSA5DIMUQGG33EMU======'.lower(), True)
b'talk is cheap, show me the code'
base64.b16encode(s)
用Base16 编码 bytes-like 对象 s。返回值为 bytes 对象。
>>> base64.b16encode(b'talk is cheap, show me the code')
b'74616C6B2069732063686561702C2073686F77206D652074686520636F6465'
base64.b16encode(s, casefold=False)
解码Base16编码过的 bytes-like 对象或 ASCII 字符串 s。
若 casefold 的值为 False,则输入只能包含大写字母。若 casefold 的值为 True,则输入可以包含小写字母。
>>> base64.b16decode(b'74616C6B2069732063686561702C2073686F77206D652074686520636F6465')
b'talk is cheap, show me the code'
>>> base64.b16decode(b'74616C6B2069732063686561702C2073686F77206D652074686520636F6465'.lower())
Traceback (most recent call last):
File "" , line 1, in <module>
File "/Users/neochen/.virtualenvs/Test/lib/python3.7/base64.py", line 267, in b16decode
raise binascii.Error('Non-base16 digit found')
binascii.Error: Non-base16 digit found
>>> base64.b16decode(b'74616C6B2069732063686561702C2073686F77206D652074686520636F6465'.lower(), True)
b'talk is cheap, show me the code'
base64.encode(input, output)
从二进制文件对象 input 中读取数据进行Base64编码,将编码的结果写入文件对象 output 中。每76个字节后将插入一个换行符 b'\n’
,并且在末尾添加一个换行符 b'\n’
。
base64.decode(input, output)
从二进制文件对象 input 中读取数据并解码,将解码的结果写入文件对象 output 中。
base64.encodebytes(s)
将包含任意二进制数据的 bytes-like 对象 s 进行Base64编码并将编码后的数据返回。 每76个字节后将插入一个换行符 b'\n’
,并且在末尾添加一个换行符 b'\n’
。
base64.decodebytes(s)
解码 bytes-like 对象 s,并返回解码后的字节。s 中必须包含一行或多行Base64编码的数据,
该模块包含多个在二进制和二进制表示的各种ASCII码之间转换的方法。 通常情况不会直接使用这些函数,而是使用像 uu、base64、binhex 这样的封装模块。 为了有较高的执行效率,该模块包含许多用 C 写的底层函数,这些底层函数被一些高级模块所使用。
a2b_*
函数接受只含有ASCII码的Unicode字符串。其他函数只接受 bytes-like 对象(如 bytes,bytearray 和其他支持缓冲区协议的对象)
binascii.a2b_uu(string)
将单行 uu 编码数据转换成二进制数据并返回。uu 编码每行的数据通常包含45 个(二进制)字节,最后一行除外。每行数据后面可能跟有空格。
binascii.b2a_uu(data, *, backtick=False)
将二进制数据转换为 ASCII 编码字符,返回值是转换后的行数据,包括换行符。 data 的长度最多为45。如果 backtick 为 Ture,则零由反引号而不是空格表示。
binascii.a2b_base64(string)
将 base64 数据块转换成二进制并以二进制数据形式返回。一次可以传递多行数据。
binascii.b2a_base64(data, *, newline=True)
将二进制数据转换为一行用 Base64 编码的ASCII字符串。返回值是转换后的行数据,如果 newline 为 True,则返回值包括换行符。该函数的输出符合rfc3548。
binascii.a2b_qp(data, header=False)
将一块带引号且可打印的数据转换成二进制数据并返回。一次可以转换多行。如果可选参数 header 存在且为 True,则数据中的下划线将被解码成空格。
binascii.b2a_qp(data, quotetabs=False, istext=True, header=False)
将二进制数据转换为一行或多行带引号且可打印编码的ASCII字符并返回。如果可选参数 quotetabs 存在且为 True,则对所有制表符和空格进行编码。如果可选参数 istext 存在且为 True,则不对新行进行编码,但将对尾随空格进行编码。如果可选参数 header 存在且为 True,则空格将被编码为下划线。如果可选参数 header 存在且为 False,则也会对换行符进行编码;否则换行转换可能会损坏二进制数据流。
binascii.a2b_hqx(string)
将 binhex4 格式的 ASCII 数据不进行 RLE 解压缩直接转换为二进制数据。该字符串应包含完整数量的二进制字节,或者(在binhex4 数据最后部分)剩余位为零。
binascii.rledecode_hqx(string)
根据 binhex4 标准对数据执行 RLE 解压缩。该算法在一个字节的数据后使用 0x90
作为重复指示符,然后计数。计数 0
指定字节值 0x90
。该例程返回解压缩的数据,输入数据以孤立的重复指示符结束的情况下,将引发 Incomplete 异常。
binascii.rlecode_hqx(string)
对数据执行binhex4风格的RLE压缩并返回结果。
binascii.b2a_hqx(string)
执行 hexbin4 类型的二进制到 ASCII 码的转换并返回结果字符串。输入数据应经过 RLE 编码,且数据长度可被3整除(除了最后一个片段)。
binascii.crc_hqx(data, value)
以 value 作为初始 CRC 计算 data 的16位 CRC 值,返回其结果。这里使用 CRC-CCITT 生成多项式 x16 + x12 + x5 + 1 ,通常表示为 0x1021
。该 CRC 被用于 binhex4 格式。
binascii.crc32(data[, value])
计算 CRC-32 ,从 value 的初始 CRC 开始计算 data 的32位校验和。默认初始 CRC 为零。该算法与 ZIP 文件校验和一致。由于该算法被设计用作校验和算法,因此不适合用作通用散列算法。使用方法如下:
print(binascii.crc32(b"hello world"))
# Or, in two pieces:
crc = binascii.crc32(b"hello")
crc = binascii.crc32(b" world", crc)
print('crc32 = {:#010x}'.format(crc))
binascii.b2a_hex(data)
返回二进制数据 data 的十六进制表示形式。 data 的每个字节都被转换为相应的2位十六进制表示形式。因此返回的字节对象的长度是 data 的两倍。
使用:bytes.hex()
方法也可以方便地实现相似的功能(但仅返回文本字符串)。
binascii.hexlify(data)
功能与 b2a_hex() 函数相同。
binascii.a2b_hex(hexstr)
返回由十六进制字符串 hexstr 表示的二进制数据。此函数功能与 b2a_hex() 相反。 hexstr 必须包含偶数个十六进制数字(可以是大写或小写),否则会引发 Error 异常。
使用:bytes.fromhex()
类方法也实现相似的功能(仅接受文本字符串参数,不限制其中的空白字符)。
binascii.unhexlify(hexstr)
功能与 a2b_hex() 函数相同。
该模块支持按顺序维护列表,而不必在每次插入之后再对列表进行排序。对于比较长的列表,比较列表中的元素的操作是比较昂贵的,这个模块中的方法是对常见方法的改进。这个模块之所以被称为 bisect,是因为其中的方法使用了二分算法。该模块的源码可以作为二分算法的示例(边界条件已经正确!)
bisect.bisect_left(a, x, lo=0, hi=len(a))
返回要插入 a 中的元素 x 的插入点索引,假定 a 是已经排序的。a 可以是 list,tuple,array 等元素可以进行排序的序列或者可迭代对象。
参数 lo 和 hi 可以用来指定列表中需要考虑的子集;默认情况下使用整个列表。如果 x 已经出现在 a 中,插入点将位于 a 中的所有的 x 的前面(在左边)。该方法假设 a 已经排序,返回值适合用作 list.insert() 的第一个参数。
返回的插入点 i 将数组 a 分成两半,以便左边的所有元素 val 满足(val < x for val in a[lo:i]
)且右边的所有元素 val 满足(val >= x for val in a[i:hi]
)。
>>> bisect.bisect_left(range(10), 7)
7
bisect.bisect_right(a, x, lo=0, hi=len(a))
类似于 bisect_left(),但是返回的插入点索引始终位于 a 中所有已存在的 x 的后面(在右边)。
返回的插入点 i 将数组 a 分成两半,以便左边的所有元素 val 满足(val < x for val in a[lo:i]
)且右边的所有元素 val 满足(val >= x for val in a[i:hi]
)。
返回的插入点 i 将数组 a 分成两半,以便左边的所有元素 val 满足(val <= x for val in a[lo:i]
)且右边的所有元素 val 满足(val > x for val in a[i:hi]
)。
>>> bisect.bisect_right(range(10), 7)
8
bisect.bisect(a, x, lo=0, hi=len(a))
与 bisect_right 函数功能完全相同
bisect.insort_left(a, x, lo=0, hi=len(a))
将 x 插入 a 中并且保持 a 仍然是有序的。这等价于 a.insert(bisect.bisect_left(a, x, lo, hi), x)
,假设 a 已经排序。请记住,O(log n)搜索由缓慢的O(n)插入步骤控制。
>>> seq = list(range(10))
>>> bisect.insort_left(seq, 7)
>>> seq
[0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9]
bisect.insort_right(a, x, lo=0, hi=len(a))
与 insort_left 相似,但会将 x 插入 a 中所有所有 x 的后边(右边)。
>>> seq = list(range(1, 11))
>>> seq
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> bisect.insort_right(seq, 7)
>>> seq
[1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10]
bisect.insort(a, x, lo=0, hi=len(a))
与 insort_right 函数功能完全一致。
Python的random模块实现了各种分布的伪随机数生成器。
对于整数,有从一定范围内统一的进行选择的函数。 对于序列,有统一选择随机元素的函数、用于生成列表的随机排列的函数、以及用于随机抽样而无需进行替换的函数。
在实数轴上,有计算均匀、正态(高斯)、对数正态、负指数、伽马和贝塔分布的函数。 要生成角度分布,可以使用 von Mises 分布。
该模块中几乎所有的函数都依赖于基本函数 random
,它在半开放区间 [0.0,1.0) 内均匀生成随机浮点数。 Python 使用 Mersenne Twister 作为核心生成器。 它产生 53-bit 精度的浮点数,周期为 2**19937-1 ,其在 C 中的底层实现既快速又线程安全。 Mersenne Twister 是现存最广泛测试的随机数生成器之一。 但是,因为完全确定性,它不适用于所有目的,并且完全不适合于加密目的。
这个模块提供的函数实际上是 random.Random
类的隐藏实例的绑定方法。 你可以自己实例化 Random
类以获取不共享状态的生成器。
如果你想使用自己设计的基础生成器,还可以子类化 Random
类:在这种情况下,重载 random()
、 seed()
、 getstate()
以及 setstate()
方法。新生成器还可以提供 getrandbits()
方法 —— 这允许 randrange()
在任意大的范围内生成选择。
该模块还提供 SystemRandom
类,它使用系统函数 os.urandom()
从操作系统提供的源生成随机数。
警告:不应将此模块的伪随机生成器用于安全目的。 有关安全性或加密用途,请参阅 secrets 模块。
random.seed(a=None, version=2)
初始化随机数生成器。
如果 a 为 None
,则使用当前系统时间。 如果操作系统提供随机源,则使用操作系统提供的随机源而不是系统时间(有关可用性的详细信息,请参阅 os.urandom()
函数)。
如果 a 是 int 类型,则直接使用。
当 version 为2时(默认的),str
、 bytes
或 bytearray
对象将被转换为 int
对象并使用它的所有位。
当 version 为1时,(用于从旧版本的Python再现随机序列),用于 str
和 bytes
的算法将生成更窄的种子范围。
注意,当种子值相等时,生成的随机数和随机数的顺序就是固定的,通过下面的例子就可以看出来:
>>> import random
>>> random.seed(100)
>>> for _ in range(10):
... print(random.randrange(10000))
...
2386
7528
7453
2863
6439
5730
7102
8304
1801
8731
>>> random.seed(100)
>>> for _ in range(10):
... print(random.randrange(10000))
...
2386
7528
7453
2863
6439
5730
7102
8304
1801
8731
>>>
random.getstate()
返回一个表示当前生成器内部状态的对象。这个方法的返回值可以传递给 setstate()
方法用来恢复生成器的状态。
random.setstate(state)
state 应该是调用 getstate()
方法获得的对象。该方法用于将生成器的内部状态恢复到调用 getstate()
方法时的状态。
random.getrandbits(k)
返回 k 位随机的整数。k位随机的整数 的意思是 每一位都是随机数的k位2进制数表示的十进制整数。
例如:
random.getrandbits(5)
表示一个每一位上都是随机数的5位2进制数,即[0, 32) 范围内的随机整数。
random.getrandbits(8)
表示一个每一位上都是随机数的8位2进制数,即[0, 256)范围内的随机整数。
此方法随MersenneTwister 生成器一起提供,其他一些生成器也可以将其作为API的可选部分提供。 如果可用,getrandbits()
将会启用 randrange()
来处理任意大范围。
random.randrange(stop)
random.randrange(start, stop[, step])
从 range(start, stop, step)
返回一个随机选择的元素。相当于 choice(range(start, stop,step))
,但实际上并没有构建一个 range 对象。
位置参数模式与 range()
函数相同。不应该使用关键字参数,因为该函数可能以意外的方式使用它们。
random.randint(a, b)
返回随机整数 N 满足 a <= N <= b
。相当于 randrange(a, b+1)
。
random.choice(seq)
从非空序列 seq 返回一个随机元素。 如果 seq 为空,则引发 IndexError
。
random.choices(population, weights=None, *, cum_weights=None, k=1)
从 population 中随机选择 k 个元素,返回由这 k 个元素组成的列表。
参数 population、weights 和 cum_weights 必须是可迭代对象。如果指定了weights 或 cum_weights,则它的长度必须与 population 相同,并且不能同时指定 weights 和 cum_weights 参数。
如果既未指定 weight 也未指定 cum_weights ,则以相等的概率进行选择。
如果指定了 weight 参数,则根据相对权重在 populaiton 中进行选择。 或者,如果给出 cum_weights 序列,则根据累积权重(可能使用 itertools.accumulate()
计算)进行选择。 例如,相对权重 [10, 5, 30, 5]
相当于累积权重 [10, 15, 45, 50]
。 在内部,相对权重在进行选择之前会转换为累积权重,因此提供累积权重可以节省工作量。
weights 或 cum_weights 中的元素可以使用任何与 random()
返回的 float
值互操作的数值类型(包括整数,浮点数和分数但不包括十进制小数)。
对于给定的种子,具有相等加权的 choices()
函数通常产生与重复调用 choice()
不同的序列。 choices()
使用的算法使用浮点运算来实现内部一致性和速度。 choice()
使用的算法默认为重复选择的整数运算,以避免因舍入误差引起的小偏差。
random.shuffle(x[, random])
将序列 x 随机打乱位置。
可选参数 random 是一个0参数函数,用于在 [0.0, 1.0) 中返回随机浮点数;默认使用 random.random()
函数。
要改变一个不可变的序列并返回一个新的打乱列表,请使用 sample(x, k=len(x))
。
请注意,即使对于长度比较小的序列 x,x 的排列总数也可以快速增长,大于大多数随机数生成器的周期。 这意味着长序列的大多数排列永远不会产生。 例如,长度为2080的序列是可以在 Mersenne Twister 随机数生成器的周期内拟合的最大序列。
random.sample(population, k)
从可迭代对象 population 中随机选择 k 个元素,每个元素只能选择一次,然后返回由这 k 个元素组成的列表。 用于无重复的随机抽样。
返回包含来自 population 的元素的新列表,同时保持 population 不变。 结果列表按选择顺序排列,因此所有子切片也将是有效的随机样本。 这允许抽奖获奖者(样本)被划分为大奖和第二名获胜者(子切片)。
population 中的元素不必是唯一的或可哈希的。 如果 population 中包含重复元素,则重复元素的每次出现都是样本中可能的选择。
要从一系列整数中选择样本,请使用 range()
对象作为参数。 对于从大量人群中采样,这种方法特别快速且节省空间:sample(range(10000000), k=60)
。
如果样本大小大于 population 大小,则引发 ValueError
。
以下函数生成特定的实值分布。如常用数学实践中所使用的那样, 函数参数以分布方程中的相应变量命名;大多数这些方程都可以在任何统计学教材中找到。
random.random()
返回 [0.0, 1.0) 范围内的下一个随机浮点数。
random.uniform(a, b)
返回一个随机浮点数 N ,当 a <= b
时 a <= N <= b
,当 b < a
时 b <= N <= a
。根据 a + (b-a) * random()
中的浮点舍入,终点 b
可以包括或不包括在该范围内。
random.triangular(low, high, mode)
返回一个随机浮点数 N ,使得 low <= N <= high
并在这些边界之间使用指定的 mode 。 low 和 high 边界默认为0和1。 mode 参数默认为边界之间的中点,给出对称分布。
random.betavariate(alpha, beta)
Beta 分布。 参数的条件是 alpha > 0
和 beta > 0
。 返回值的范围介于 0 和 1 之间。
random.expovariate(lambd)
指数分布。 lambd 是 1.0 除以所需的平均值,它应该是非零的。 (该参数本应命名为 lambda ,但由于 lambda 已经是 Python 中的关键字,所以改为 lamdb)如果 lambd 为正,则返回值的范围为 0 到正无穷大;如果 lambd 为负,则返回值从负无穷大到 0。
random.gammavariate(alpha, beta)
Gamma 分布。 ( 不是 gamma 函数! ) 参数的条件是 alpha > 0
且 beta > 0
。
概率分布函数是:
pdf(x) = (x ** (alpha - 1) * math.exp(-x / beta)) / math.gamma(alpha) * beta ** alpha
random.gauss(mu, sigma)
高斯分布。 mu 是平均值,sigma 是标准差。 这比下面定义的 normalvariate()
函数略快。
random.lognormvariate(mu, sigma)
对数正态分布。 如果你采用这个分布的自然对数,你将得到一个正态分布,平均值为 mu 和标准差为 sigma。 mu 可以是任何值,sigma 必须大于零。
random.normalvariate(mu, sigma)
正态分布。 mu 是平均值,sigma 是标准差。
random.vonmisesvariate(mu, kappa)
mu 是平均角度,以弧度表示,介于0和 2*pi 之间,kappa 是浓度参数,必须大于或等于零。 如果 kappa等于零,则该分布在0到 2**pi* 的范围内减小到均匀的随机角度。
random.paretovariate(alpha)
帕累托分布。 alpha 是形状参数。
random.weibullvariate(alpha, beta)
威布尔分布。 alpha 是比例参数,beta 是形状参数。
class random.Random([seed])
该类实现了该模块所使用的默认伪随机数生成器。
class random.SystemRandom([seed])
使用 os.urandom()
函数的类,用从操作系统提供的源生成随机数。 这并非适用于所有系统。 也不依赖于软件状态,序列不可重现。 因此,seed()
方法没有效果而被忽略。 getstate()
和 setstate()
方法如果被调用则引发 NotImplementedError
异常。
该模块为许多不同的安全散列和消息摘要算法实现了一个公共接口。包括FIPS安全哈希算法SHA1、SHA224、SHA256、SHA384和SHA512(在FIPS 180-2中定义)以及RSA的MD5算法(在Internet RFC 1321中定义)。术语 “安全散列” 和 “消息摘要” 是可以互换的。较老的算法称为消息摘要。现代术语是安全散列。
每种哈希类型都有一个构造函数。所有返回的哈希对象都具有相同的简单接口。例如:使用 sha256() 创建一个SHA-256散列对象,现在可以使用 *update()*方法向这个对象提供 bytes-like 对象(通常是 bytes)。在任何时候,都可以使用 digest() 或 hexdigest() 方法向它请求数据连接的摘要。
该模块中始终存在的哈希算法构造函数有 sha1()、sha224()、sha256()、sha384()、sha512()、blake2b() 和blake2s()。md5() 通常也是可用的,但如果使用罕见的Python “FIPS兼容” 构建,则可能会缺少 md5()。根据Python在平台上使用的OpenSSL库,还可能提供其他算法。在大多数平台上,sha3_224()、sha3_256()、sha3_384()、sha3_512()、shake_128() 和 shake_256() 也是可用的。
该模块提供了以下常量属性:
hashlib.algorithms_guaranteed
包含此模块保证在所有平台上支持的哈希算法名称的集合。注意,尽管一些上游供应商提供了一个奇怪的 “符合FIPS” 的Python构建而将其排除在外,但是 md5 仍然包含在这个列表中。
>>> hashlib.algorithms_guaranteed
{
'sha3_384', 'sha384', 'sha3_512', 'sha3_256', 'sha3_224', 'blake2b', 'md5', 'shake_256', 'blake2s', 'sha1', 'sha224', 'sha256', 'sha512', 'shake_128'}
hashlib.algorithms_available
包含在运行的Python解释器中可用的哈希算法名称的集合。这些名称将在传递给 new() 时被识别。
algorithms_guaranteed 总是该属性的一个子集。相同的算法可能会在这个集合中以不同的名称出现多次(多亏了OpenSSL)。
>>> hashlib.algorithms_available
{
'sha3_384', 'ecdsa-with-SHA1', 'blake2s', 'sha1', 'MD5', 'sha256', 'sha3_256', 'ripemd160', 'md4', 'blake2b', 'SHA384', 'shake_256', 'SHA512', 'dsaEncryption', 'sha224', 'SHA1', 'dsaWithSHA', 'sha', 'sha512', 'shake_128', 'sha3_224', 'md5', 'MD4', 'MDC2', 'SHA256', 'RIPEMD160', 'sha384', 'mdc2', 'DSA', 'SHA', 'DSA-SHA', 'whirlpool', 'SHA224', 'sha3_512'}
>>> hashlib.algorithms_guaranteed.issubset(hashlib.algorithms_available)
True
要计算散列值,需要先调用以下命名构造函数,其名称与所表示的算法是相同的:
这些函数返回的摘要对象实例 d 有以下方法和属性:
d.update(data)
使用新数据更新散列。data 必须是 bytes-likes 对象。重复调用与使用串联的数据进行单次调用的效果相同。
d.digest()
将摘要作为原始字节字符串返回。
d.hexdigest()
返回文本字符串,摘要的值编码为一系列十六进制数字。
d.copy()
返回摘要副本,副本保留原摘要的内部状态。
d.digest_size
返回散列的字节大小。
d.block_size
散列算法的内部块字节大小。
d.name
返回当前摘要对象所使用的哈希算法的规范命名。始终为小写,并且始终可以作为 new() 方法的参数用以生成新的摘要对象。
>>> d = hashlib.sha256() # 使用"SHA256"算法初始化一个散列对象
>>> d
<sha256 HASH object @ 0x10d5f9b98>
>>> d.update(b'hello world') # 计算"hello world"的散列值
>>> d.digest() # 获取表示"hello world"摘要的字节字符串
b"\xb9M'\xb9\x93M>\x08\xa5.R\xd7\xda}\xab\xfa\xc4\x84\xef\xe3zS\x80\xee\x90\x88\xf7\xac\xe2\xef\xcd\xe9"
>>> d.hexdigest() # 获取使用十六进制数字表示的"hello world"摘要的字符串
'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'
>>> d.digest_size # 获取摘要的字节大小
32
>>> d.block_size # 获取摘要的内部块字节大小
64
>>> d1 = hashlib.sha256()
>>> d1.update(b'hello')
>>> d1.update(b' world')
>>> d1.hexdigest()
'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'
>>> d.hexdigest() == d1.hexdigest() # 可以看到,使用 'b"hello"' 和 'b" world"'重复调用"update()" 方法与使用 'b"hello world"'单次单次调用"update()" 方法得到的摘要是相同的
True
该模块还提供了一个可选的构造方法:
hashlib.new(name[, data])
这是一个通用的构造函数,name 是表示散列算法名称的字符串,可选的 data 参数用以指定用于更新散列的数据,必须是 bytes-like 对象。它还允许访问上面列出的散列以及OpenSSL库可能提供的任何其他算法。命名构造函数比该构造函数快得多,应该作为首选。
>>> d2 = hashlib.new('sha256', b'hello world')
>>> d2.hexdigest()
'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'
shake_128 和 shake_256 提供长度可变的摘要,因此,它们的 digest() 和 hex_digest() 方法需要一个用来指定长度的参数 length,并且最大长度不受SHAKE算法的限制。
>>> d3 = hashlib.new('shake_256', b'hello world')
>>> d3
<_sha3.shake_256 object at 0x10d451bd0>
>>> d3.hexdigest(36)
'369771bb2cb9d2b04c1d54cca487e372d9f187f73f7ba3f65b95c8ee7798c527f4f3c2d5'
>>> d3.digest(36)
b"6\x97q\xbb,\xb9\xd2\xb0L\x1dT\xcc\xa4\x87\xe3r\xd9\xf1\x87\xf7?{\xa3\xf6[\x95\xc8\xeew\x98\xc5'\xf4\xf3\xc2\xd5"
密钥派生和密钥拓展算法是为安全的密码哈希而设计的。诸如 sha1(password)
这样的简单算法不能抵抗暴力攻击。一个好的密码哈希函数必须是可调谐的、 速度慢的,并且包括一个 salt。
hashlib.pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None)
该函数提供了基于 PKCS#5
密码的密钥派生函数2。它使用 HMAC 作为伪随机函数。
字符串 hash_name 是 HMAC 的散列摘要算法的期望名称,例如。sha1 或 sha256。
password 和 salt 必须是bytes 或 bytearray 对象。应用程序和库应该将 password 限制为合理的长度(例如1024)。salt 应该来自一个合适的源,例如 os.urandom(),大约16个或更多字节。
iterations 应根据哈希算法和计算能力来选择。截至2013年,建议至少进行 100000
次SHA-256迭代。
dklen 是派生键的长度。如果 dklen 为 None,则使用散列算法 hash_name 的摘要大小,例如SHA-512使用64。
>>> import hashlib, binascii
>>> dk = hashlib.pbkdf2_hmac('sha256', b'password', b'salt', 100000)
>>> binascii.b2a_hex(dk)
b'0394a2ede332c9a13eb82e9b24631604c31df978b4e2f0fbd2c549944f9d79a5'
hashlib.scrypt(password, *, salt, n, r, p, maxmem=0, dklen=64)
该函数提供了RFC 7914中定义的基于scrypt密码的密钥派生函数。
password 和 salt 必须是 bytes-like 对象。应用程序和库应该将密码限制为合理的长度(例如1024)。salt 应该来自一个合适的源,例如 os.urandom(),大约16个或更多字节。
n 是CPU/内存的成本因子,r 是块大小,p 是并行化因子,maxmem 限制内存(OpenSSL 1.1.0默认为32 MiB)。dklen 是派生键的长度。
该模块实现 RFC 2104 中描述的 HMAC算法。
该模块包含如下两个方法:
hmac.new(key, msg=None, digestmod=None)
返回一个新的 hmac 对象。key 必须是 bytes 或 bytearray 对象,用于提供密钥。如果指定了 msg 参数,则调用 update(msg) 方法。digestmod 是要使用的HMAC对象的摘要名称、摘要构造函数或模块。它支持任何适合于 hashlib.new() 的名称,并默认为 hashlib.md5() 构造函数。
注意:MD5作为 digestmod 的默认的摘要从3.4 版本开始不推荐使用,3.8 版本将会移除。
>>> d = hmac.new(hashlib.new('md5', b'password').digest(), b'hello world', 'sha256')
>>> d
<hmac.HMAC object at 0x10d906c18>
>>> d.hexdigest()
'09b75fd147dd72e4618366e530034ca57f97a2158e0b439af9a26f7008a3e6fe'
hmac.digest(key, msg, digest)
返回表示给定密钥和摘要的消息的摘要的 bytes 对象。该函数等价于 HMAC(key, msg, digest).digest()
,但是使用了优化的C或内联实现,这对于适合内存的消息更快。参数 key、msg 和 digest 与 new() 中的含义相同。
CPython实现细节,优化后的C实现只在摘要是一个字符串和一个摘要算法的名称时使用,该算法由OpenSSL支持。
>>> digest = hmac.digest(hashlib.new('md5', b'password').digest(), b'hello world', 'sha256')
>>> digest
b'\t\xb7_\xd1G\xddr\xe4a\x83f\xe50\x03L\xa5\x7f\x97\xa2\x15\x8e\x0bC\x9a\xf9\xa2op\x08\xa3\xe6\xfe'
一个HMAC对象包含如下实例方法和实例属性:
HMAC.update(msg)
使用 msg 更新hmac对象。重复调用与使用串联的参数进行单次调用的效果相同,即:
m.update(a);m.update(b)
与 m.update(a + b)
等价。
HMAC.digest()
返回到目前为止传递给 update() 方法的字节摘要。这个 bytes 对象的长度将与给定给构造函数的摘要的digest_size 相同。它可以包含非ASCII字节,包括空字节。
警告:在验证例程中将 digest() 的输出与外部提供的摘要进行比较时,建议使用 compare_digest() 函数而不是
==
操作符来降低定时攻击的脆弱性。
HMAC.hexdigest()
与 digest() 类似,只是摘要作为字符串返回,长度是只包含十六进制数字长度的两倍。这可以用于在电子邮件或其他非二进制环境中安全地交换值。
警告:在验证例程中将 hexdigest() 的输出与外部提供的摘要进行比较时,建议使用 compare_digest() 函数而不是
==
操作符来降低定时攻击的脆弱性。
HMAC.copy()
返回hmac对象的副本(克隆)。这可以用来有效地计算共享一个公共初始子字符串的字符串摘要。
HMAC.compare_digest(a, b)
用于比较两个摘要。如果相同,则返回 True,如果不同,则返回 False。该函数使用了一种设计方法,通过避免基于内容的短路行为来防止计时分析,使其适合于密码学。a 和 b 必须具有相同的类型:要么是str(仅限ASCII,例如由 HMAC.hexdigest()
返回),要么是 bytes-like 对象。
注意:如果 a 和 b 的长度不同,或者发生错误,定时攻击理论上可以揭示关于 a 和 b 的类型和长度的信息,但不能揭示它们的值。
>>> digest1 = hmac.digest(hashlib.new('md5', b'password').digest(), b'hello world1', 'sha256')
>>> digest2 = hmac.digest(hashlib.new('md5', b'password').digest(), b'hello world2', 'sha256')
>>> hmac.compare_digest(digest1, digest2)
False
HMAC.digest_size
HMAC对象实例的摘要的的字节长度。
HMAC.block_size
哈希算法的内部块的字节大小。
HMAC.name
HMAC的规范名称。通常是小写。例如 hmac-md5。
该模块用于生成适用于管理密码、帐户身份验证、安全令牌和相关机密等数据的加密强随机数。
特别是,在random模块中,应该优先使用 secret,而不是默认的伪随机数生成器,它是为建模和仿真而设计的,而不是安全性或密码学。
secret模块提供对操作系统提供的最安全的随机源的访问。
class secrets.SystemRandom
使用操作系统提供的最高质量源生成随机数的类。请查看 random.SystemRandom 了解更多细节。
secrets.choice(sequence)
从非空序列中返回一个随机选择的元素。
secrets.randbelow(n)
返回在 range(0, n)
范围内的一个随机整数。
secrets.randbits(k)
返回 k 位随机的整数。k位随机的整数 的意思是 每一位都是随机数的k位2进制数表示的十进制整数。
该模块提供了生成安全令牌的函数。适用于密码重置、难以猜测的URL等应用程序。
secrets.token_bytes([nbytes=None])
返回长度为 nbytes 的随机字节字符串。如果未提供 nbytes 参数或者参数值为 None,则会使用一个合适的默认值。
>>> secrets.token_bytes(16)
b'Gd\xf0q+4\x7f\xbd.\xa1\xfe\x80r\xbd\x95\xa0'
secrets.token_hex([nbytes=None])
返回使用十六进制数字表示的随机文本字符串,字符串包含 nbytes 随机字节,每个字节转换为两个十六进制数字。如果未指定 nbytes 参数或者参数值为 None,则使用一个合理的默认值。
>>> secrets.token_hex(16)
'a261cdadc2469a7383a21f325ab26f21'
secrets.token_urlsafe([nbytes=None])
返回一个随机的URL安全文本字符串,其中包含 nbytes 随机字节。文本是Base64编码的,因此平均每个字节大约产生1.3个字符。如果未指定 nbytes 参数或者参数值为 None,则使用一个合理的默认值。
>>> token_urlsafe(16)
'Drmhze6EPcv0fN_81Bj-nA'
为了防止暴力攻击,令牌需要具有足够的随机性。不幸的是,随着计算机的性能变得越来越强大,并且能够在更短的时间内做出更多的猜测,被认为足够的量必然会增加。截至2015年,人们认为32字节(256位)的随机性足以满足secret模块的典型用例。
对于那些希望管理自己的令牌长度的人,可以通过为各种 token_* 函数提供 nbytes 参数显式地指定令牌的随机性。该参数被视为要使用的随机字节数。
否则,如果没有提供参数,或者参数为 None,则 token_* 函数将使用合理的默认值。
注意:该缺省值随时可能更改,包括在维护发布期间。
secrets.compare_digest(a, b)
如果字符串 a 和 b 相等,则返回 True,否则返回 False。
使用该方法可以降低定时攻击的风险。有关更多细节,请参见 hmac.compare_digest()。
本节将介绍使用 secrets 模块管理基本安全级别的方法和最佳实践。
生成一个8个字符的字母数字密码:
import string
alphabet = string.ascii_letters + string.digits
password = ''.join(choice(alphabet) for i in range(8))
注意:应用程序不应该以可恢复的格式存储密码,无论是纯文本还是加密的。应该使用加密强单向(不可逆)哈希函数对它们进行加盐和哈希。
生成包含至少一个小写字符、至少一个大写字符和至少三个数字的10个字符的字母数字密码:
>>> import string
>>> from secrets import choice
>>> def get_token():
... alphabet = string.ascii_letters + string.digits
... while True:
... password = ''.join(choice(alphabet) for _ in range(10))
... if (any(c.islower() for c in password)
... and any(c.isupper() for c in password)
... and sum(c.isdigit() for c in password) >= 3):
... return password
...
>>> print(get_token())
7xca361JhZ
生成一个 XKCD风格的密码:
>>> from secrets import choice
>>> # 在标准的Linux系统上,使用一个方便的字典文件。其他平台可能需要提供自己的单词列表。
... with open('/usr/share/dict/words') as f:
... words = [word.strip() for word in f]
... password = ' '.join(choice(words) for i in range(4))
...
>>> password
'Macaranga moveability underwrought trimesinic'
生成一个难以猜测的临时URL,其中包含适合密码恢复应用程序的安全令牌:
>>> url = 'https://mydomain.com/reset=' + secrets.token_urlsafe()
>>> url
'https://mydomain.com/reset=2VzXzxF6fYkw7VCmkZy2_r7PeLpQCqBzrrrhRvouOE8'