xxHash 的 Python 绑定
项目描述
xxhash 是Yann Collet为xxHash库提供的 Python 绑定。
安装
$ pip install xxhash
从源安装
$ pip install --no-binary xxhash xxhash
先决条件
在 Debian/Ubuntu 上:
$ apt-get install python-dev gcc
在 CentOS/Fedora 上:
$ yum install python-devel gcc redhat-rpm-config
链接到 libxxhash.so
默认情况下,python-xxhash 将使用捆绑的 xxHash,我们可以通过指定 ENV var XXHASH_LINK_SO来更改它:
$ XXHASH_LINK_SO=1 pip install --no-binary xxhash xxhash
用法
模块版本及其后端 xxHash 库版本可以分别使用模块属性VERSION和XXHASH_VERSION检索。
>>> import xxhash
>>> xxhash.VERSION
'2.0.0'
>>> xxhash.XXHASH_VERSION
'0.8.0'
这个模块是 hashlib-compliant,这意味着你可以像hashlib.md5一样使用它。
update() – 使用附加字符串更新当前摘要digest() – 返回当前的摘要值hexdigest() – 将当前摘要作为十六进制数字字符串返回intdigest() – 以整数形式返回当前摘要copy() – 返回当前 xxhash 对象的副本reset() – 重置状态
md5 摘要返回字节,但原始的 xxh32 和 xxh64 C API 返回整数。虽然此模块与 hashlib 兼容,但还提供了intdigest()来获取整数摘要。
此模块提供的哈希算法的构造函数是xxh32()和xxh64()。
例如,要获取字节串b'Nobody 检查垃圾邮件重复'的摘要:
>>> import xxhash
>>> x = xxhash.xxh32()
>>> x.update(b'Nobody inspects')
>>> x.update(b' the spammish repetition')
>>> x.digest()
b'\xe2);/'
>>> x.digest_size
4
>>> x.block_size
16
更浓缩:
>>> xxhash.xxh32(b'Nobody inspects the spammish repetition').hexdigest()
'e2293b2f'
>>> xxhash.xxh32(b'Nobody inspects the spammish repetition').digest() == x.digest()
True
一个可选的种子(默认为 0)可用于以可预测的方式改变结果:
>>> import xxhash
>>> xxhash.xxh64('xxhash').hexdigest()
'32dd38952c4bc720'
>>> xxhash.xxh64('xxhash', seed=20141025).hexdigest()
'b559b98d844e0635'
>>> x = xxhash.xxh64(seed=20141025)
>>> x.update('xxhash')
>>> x.hexdigest()
'b559b98d844e0635'
>>> x.intdigest()
13067679811253438005
请注意,xxh32 采用无符号 32 位整数作为种子,而 xxh64 采用无符号 64 位整数。尽管无符号整数溢出是已定义的行为,但最好不要让它发生:
>>> xxhash.xxh32('I want an unsigned 32-bit seed!', seed=0).hexdigest()
'f7a35af8'
>>> xxhash.xxh32('I want an unsigned 32-bit seed!', seed=2**32).hexdigest()
'f7a35af8'
>>> xxhash.xxh32('I want an unsigned 32-bit seed!', seed=1).hexdigest()
'd8d4b4ba'
>>> xxhash.xxh32('I want an unsigned 32-bit seed!', seed=2**32+1).hexdigest()
'd8d4b4ba'
>>>
>>> xxhash.xxh64('I want an unsigned 64-bit seed!', seed=0).hexdigest()
'd4cb0a70a2b8c7c1'
>>> xxhash.xxh64('I want an unsigned 64-bit seed!', seed=2**64).hexdigest()
'd4cb0a70a2b8c7c1'
>>> xxhash.xxh64('I want an unsigned 64-bit seed!', seed=1).hexdigest()
'ce5087f12470d961'
>>> xxhash.xxh64('I want an unsigned 64-bit seed!', seed=2**64+1).hexdigest()
'ce5087f12470d961'
digest()返回整数摘要的大端表示的字节:
>>> import xxhash
>>> h = xxhash.xxh64()
>>> h.digest()
b'\xefF\xdb7Q\xd8\xe9\x99'
>>> h.intdigest().to_bytes(8, 'big')
b'\xefF\xdb7Q\xd8\xe9\x99'
>>> h.hexdigest()
'ef46db3751d8e999'
>>> format(h.intdigest(), '016x')
'ef46db3751d8e999'
>>> h.intdigest()
17241709254077376921
>>> int(h.hexdigest(), 16)
17241709254077376921
除了上面提到的 xxh32/xxh64 之外,还提供了 oneshot 函数,所以我们可以避免在堆上分配 XXH32/64 状态:
xxh32_digest(字节,种子=0)xxh32_intdigest(字节,种子=0)xxh32_hexdigest(字节,种子=0)xxh64_digest(字节,种子=0)xxh64_intdigest(字节,种子=0)xxh64_hexdigest(字节,种子=0)
>>> import xxhash
>>> xxhash.xxh64('a').digest() == xxhash.xxh64_digest('a')
True
>>> xxhash.xxh64('a').intdigest() == xxhash.xxh64_intdigest('a')
True
>>> xxhash.xxh64('a').hexdigest() == xxhash.xxh64_hexdigest('a')
True
>>> xxhash.xxh64_hexdigest('xxhash', seed=20141025)
'b559b98d844e0635'
>>> xxhash.xxh64_intdigest('xxhash', seed=20141025)
13067679811253438005L
>>> xxhash.xxh64_digest('xxhash', seed=20141025)
'\xb5Y\xb9\x8d\x84N\x065'
In [1]: import xxhash
In [2]: %timeit xxhash.xxh64_hexdigest('xxhash')
268 ns ± 24.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [3]: %timeit xxhash.xxh64('xxhash').hexdigest()
416 ns ± 17.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
XXH3 哈希自 v2.0.0 (xxHash v0.8.0) 起可用,它们是:
流媒体类:
xxh3_64xxh3_128
Oneshot 功能:
xxh3_64_digest(字节,种子=0)xxh3_64_intdigest(字节,种子=0)xxh3_64_hexdigest(字节,种子=0)xxh3_128_digest(字节,种子=0)xxh3_128_intdigest(字节,种子=0)xxh3_128_hexdigest(字节,种子=0)
和别名:
xxh128 = xxh3_128xxh128_digest = xxh3_128_digestxxh128_intdigest = xxh3_128_intdigestxxh128_hexdigest = xxh3_128_hexdigest
注意事项
种子溢出
xxh32 将无符号 32 位整数作为种子,xxh64 将无符号 64 位整数作为种子。确保种子大于或等于0。
字节序
从 python-xxhash 0.3.0 开始,digest()返回 整数摘要的大端表示形式的字节。它曾经是小端的。
不要在 HMAC 中使用 XXHASH
虽然您可以使用 xxhash 作为HMAC哈希函数,但强烈建议不要这样做。
xxhash不是加密散列函数,它是一种针对速度和质量的非加密散列算法。不要将 xxhash 放在需要加密哈希函数的任何位置。
版权和许可
版权所有 (c) 2014-2020 杜悦 - https://github.com/ifduyue
变更日志
v3.0.0 2022-02-25
新设置的算法可用列出了xxhash 包中所有已实现的算法。
将 xxHash 升级到 v0.8.1。
放弃对 EOL Python 版本的支持,从现在开始需要 python >= 3.6。
迁移到 github 操作并为 macOS 构建 arm64 轮子。
始终释放 GIL。
v2.0.2 2021-04-15
修复 Travis CI OSX dpl python2.7 get-pip.py 错误
v2.0.1 2021-04-15
仅触发 Python 3.9 轮子构建。
v2.0.0 2020-08-03
需要 xxHash 版本 >= v0.8.0
升级 xxHash 到 v0.8.0
XXH3 哈希:xxh3_64,xxh3_128,以及它们的 oneshot 函数
v1.4.4 2020-06-20
升级 xxHash 到 v0.7.3
停止使用 PEP393 已弃用的 API
使用 XXH(32|64)_canonicalFromHash 替换 u2bytes 和 ull2bytes
v1.4.3 2019-11-12
升级 xxHash 到 v0.7.2
Python 3.8 轮子
v1.4.2 2019-10-13
修复:setup.py 在读取 README.rst 时失败且默认编码不是 UTF-8
v1.4.1 2019-08-27
已修复:源 tarball 中缺少 xxh3.h
v1.4.0 2019-08-25
升级 xxHash 到 v0.7.1
v1.3.0 2018-10-21
车轮现在是自动构建的
将 CFFI 变体拆分为单独的包ifduyue/python-xxhash-cffi
v1.2.0 2018-07-13
添加 oneshot 函数 xxh{32,64}_{,int,hex}digest
v1.1.0 2018-07-05
允许输入大于 2GB
在足够大的输入上释放 GIL
放弃对 Python 3.2 的支持
v1.0.1 2017-03-02
主动释放状态,而不是将其委托给 ffi.gc
v1.0.0 2017-02-10
修复了 copy() 段错误
添加了 CFFI 变体
v0.6.3 2017-02-10
修复了 copy() 段错误
v0.6.2 2017-02-10
升级 xxHash 到 v0.6.2
v0.6.1 2016-06-26
升级 xxHash 到 v0.6.1
v0.5.0 2016-03-02
升级 xxHash 到 v0.5.0
v0.4.3 2015-08-21
将 xxHash 升级到 r42
v0.4.1 2015-08-16
将 xxHash 升级到 r41
v0.4.0 2015-08-05
添加方法重置
将 xxHash 升级到 r40
v0.3.2 2015-01-27
修复了文档字符串中的一些拼写错误
v0.3.1 2015-01-24
将 xxHash 升级到 r39
v0.3.0 2014-11-11
将 digest() 从整数摘要的小端表示更改为大端表示。此更改破坏了兼容性(digest() 结果不同)。
v0.2.0 2014-10-25
使这个包符合 hashlib 标准
v0.1.3 2014-10-23
将 xxHash 更新为 r37
v0.1.2 2014-10-19
改进:检查 XXHnn_init() 返回值。
将 xxHash 更新为 r36
v0.1.1 2014-08-07
改进:现在可以使用 Visual C++ 编译器构建。
v0.1.0 2014-08-05
新增:XXH32 和 XXH64 类型,支持部分更新。
修复:在 Python 3.4 下构建
v0.0.2 2014-08-03
新:支持 Python 3
v0.0.1 2014-07-30
新:xxh32 和 xxh64