重复散列任意Python元组

重复散列任意Python元组,python,hash,Python,Hash,我正在编写一个专门的单元测试工具,它需要保存测试结果,以便将来进行比较。因此,我需要能够一致地将传递给每个测试的参数映射到使用每个版本的参数运行测试函数的测试结果。我希望有一种方法可以对元组进行散列,并使用该散列来命名存储测试结果的文件 我的第一个冲动是对参数的元组调用hash(),但这当然行不通,因为hash现在在解释器实例之间是随机的 我很难想出一种方法来处理元组中可能存在的任意元素(我想将它限制为int、float、string和list\tuple这三种元素的组合是可以的)。有什么想法吗

我正在编写一个专门的单元测试工具,它需要保存测试结果,以便将来进行比较。因此,我需要能够一致地将传递给每个测试的参数映射到使用每个版本的参数运行测试函数的测试结果。我希望有一种方法可以对元组进行散列,并使用该散列来命名存储测试结果的文件

我的第一个冲动是对参数的元组调用
hash()
,但这当然行不通,因为
hash
现在在解释器实例之间是随机的

我很难想出一种方法来处理元组中可能存在的任意元素(我想将它限制为int、float、string和list\tuple这三种元素的组合是可以的)。有什么想法吗

我曾经考虑过使用元组的
repr
,或者对其进行pickle处理,但是repr不能保证为相同的输入生成字节对字节的相同输出,而且我认为pickle也不是(是吗?)


我已经看到了,但答案都是基于同样的假设,不再成立,也不会真正转化为这个问题,很多讨论都是关于使哈希不依赖于出现的顺序项,我确实希望哈希依赖于顺序。

不确定我是否完全理解你的问题,但我会尝试一下

在进行哈希之前,只需将结果序列化为JSON字符串,并对JSON字符串进行哈希计算

params = (1, 3, 2)
hashlib.sha224(json.dumps(params)).hexdigest()
# '5f0f7a621e6f420002d54ee28b0c169b8112ef72d8a6b60e6a25171c'
如果您的参数是字典,请使用sort_keys=True以确保您的键已排序

params = {'b': 123, 'c': 345}
hashlib.sha224(json.dumps(params, sort_keys=True)).hexdigest()
# '2e75966ce3f1185cbfb4eccc49d5552c08cfb7502a8765fe1dce9303'

简单测试的一种方法是在启动脚本的环境中设置
pythonhasheed=0
,例如在
bash
中,执行以下操作:

export PYTHONHASHSEED=0

我会将参数的元组和结果pickle到同一个文件中,该文件的名称是散列参数元组。这样,您就不必担心随机化,因为原始元组在文件中。@DYZ对,我也在这样做,但我需要对元组进行重复哈希,以便能够在第一时间找到文件。可以接受吗?@ShadowRanger That。。。我想这是可行的,但它非常不雅观,从技术上讲,这意味着有人可以通过一个精心编制的合并请求来处理我的CI服务器。@Schilcote:所以,如果这是一个面向公众的服务器,这是一个坏主意;这个问题听起来像是针对可重复的(假定的本地)单元测试。JSON结果是否保证每次都是相同的?@Schilcote对于列表或元组(以及其中的任何稳定原语)应该是相同的。如果您序列化的是元组/列表,那么是的。对于字典,您可以将
sort_keys
设置为
True
@DYZ:注意:
sort_keys
仅在Python 3上工作,如果键是同质类型(或者为所有异构类型对定义了比较,例如,
int
float
的混合是可以的,但是
int
str
不是)。在Python2上,回退比较允许它(通常)工作(尽管不一定是可重复的,因为相同类型的回退比较基于内存地址,这是不可重复的),但在Python3上,您只会得到一个
TypeError
;在面向公众的web服务上执行此操作将使您面临拒绝服务攻击(散列随机化就是为了保护您免受攻击而设计的)。禁用has随机化将无助于解决
散列(-1)=散列(-2)
的问题,因为除-1散列为-2外,所有整数都会自行散列(至少最近与Python 3.8.2一样)@mkoistinen:当然?但这是散列的一个问题,一般来说与这个答案无关。散列随机化的目的是消除创建冲突散列的能力;禁用它可以让你找到冲突字符串,就像找到冲突的
int
s一样容易。
int
散列
将成为poten无论你是否禁用它,我的回复都不是对你有用的帖子的批评,我也没有投反对票,而是我的评论是对其他试图使用类似于原始问题的
hash()
的人的警告。