我们有大量的 Python 代码,它们接受一些输入并产生一些输出。

我们想保证,给定相同的输入,无论 python 版本或本地环境如何,我们都会产生相同的输出。 (例如,代码是在 Windows、Mac 还是 Linux 上以 32 位或 64 位运行)

我们一直在自动化测试套件中执行这一点,方法是在使用和不使用 python 的 -R 选项的情况下运行我们的程序并比较输出,假设这会消除我们的输出意外结束的任何点,这些点取决于 dict 上的迭代。 (我们代码中最常见的不确定性来源)

然而,当我们最近调整我们的代码以支持 python 3 时,我们发现了一个地方,我们的输出部分依赖于 dict 的迭代,该迭代使用 int 作为键。与 python2 相比,此迭代顺序在 python3 中发生了变化,并使我们的输出不同。我们现有的测试(全部在 python 2.7 上)没有注意到这一点。 (因为 -R 不影响 int 的哈希值)一旦找到,很容易修复,但我们希望早点找到它。

有什么方法可以进一步对我们的代码进行压力测试,并让我们相信我们已经根据 Python 版本/环境中可能不同的某些内容隐式地找出了所有最终的位置?我认为像 -RPYTHONHASHSEED 之类的东西适用于数字以及 strbytes 和 0x21418 其他对象可以工作,但是 0x2313 可以打开其他对象。然而,如果可能的话,我希望我们的自动化测试机器只需要安装一个 python 版本。

另一种可接受的替代方法是通过 pypy 调整运行我们的代码,以便在从 datetime 迭代项目时使用不同的顺序;我认为我们的代码在 pypy 上运行,尽管我们从未明确支持过它。但是,如果某个 pypy 专家给了我们一种方法来在不同的运行中调整字典迭代顺序,那么我们将努力实现这一目标。

最佳答案

在这里使用 PyPy 并不是最好的选择,因为它总是在其 dicts 中保留插入顺序(使用一种使 dicts 使用更少内存的方法)。我们当然可以让它改变枚举字典的顺序,但它违背了这一点。

相反,我建议修改 CPython 源代码以更改哈希在 dictobject.c 中的使用方式。例如,在每个 hash = PyObject_Hash(key); if (hash == -1) { ..error.. }; 之后,您可以添加 hash ^= HASH_TWEAK; 并使用 HASH_TWEAK 的不同值编译不同版本的 CPython。 (我曾经做过这样的事情,但我再也找不到了。您需要注意哈希值是原始值还是修改后的值。)

关于python - 等效于影响整数散列的python的-R选项,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44324494/

10-12 23:10