Skip to main content

xxHash 的 Python 绑定

项目描述

Github 操作状态 最新版本 支持的 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 库版本可以分别使用模块属性VERSIONXXHASH_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_64
xxh3_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_128
xxh128_digest = xxh3_128_digest
xxh128_intdigest = xxh3_128_intdigest
xxh128_hexdigest = xxh3_128_hexdigest

注意事项

种子溢出

xxh32 将无符号 32 位整数作为种子,xxh64 将无符号 64 位整数作为种子。确保种子大于或等于0

字节序

从 python-xxhash 0.3.0 开始,digest()返回 整数摘要的大端表示形式的字节。它曾经是小端的。

不要在 HMAC 中使用 XXHASH

虽然您可以使用 xxhash 作为HMAC哈希函数,但强烈建议不要这样做。

xxhash不是加密散列函数,它是一种针对速度和质量的非加密散列算法。不要将 xxhash 放在需要加密哈希函数的任何位置。

变更日志

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_64xxh3_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

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