Подтвердить что ты не робот

Эквивалент опции python -R, которая влияет на хэш ints

У нас есть большая коллекция кода python, которая принимает некоторый ввод и производит некоторый вывод.

Мы хотели бы гарантировать, что, учитывая идентичный ввод, мы производим идентичный вывод независимо от версии python или локальной среды. (например, выполняется ли код в Windows, Mac или Linux в 32-разрядной или 64-разрядной версии)

Мы применяем это в автоматическом тестовом наборе, запустив нашу программу как с опцией -R, так и без нее, и сравним вывод, предполагая, что вытряхнете любые пятна, где наш выход случайно зависнет от итерации a dict. (Самый распространенный источник недетерминизма в нашем коде)

Однако, поскольку мы недавно скорректировали наш код, чтобы также поддерживать python 3, мы обнаружили место, где наш вывод зависел частично от итерации над dict, которая использовала int в качестве ключей. Этот порядок итераций изменился в python3 по сравнению с python2 и делал наш вывод другим. Наши существующие тесты (все на python 2.7) этого не заметили. (Потому что -R не влияет на хэш int s). После обнаружения его легко исправить, но мы хотели бы его найти раньше.

Есть ли способ дальнейшего стресс-тестирования нашего кода и дать нам уверенность в том, что мы выяснили все места, где мы закончили неявно в зависимости от того, что может быть различным в версиях/средах python? Я думаю, что что-то вроде -R или PYTHONHASHSEED, которое применяется к числам, а также к объектам str, bytes и datetime, может работать, но я открыт для других подходов. Тем не менее, мне хотелось бы, чтобы наша автоматическая тестовая машина нуждалась только в одной версии python, если это возможно.

Другой приемлемой альтернативой будет какой-то способ запустить наш код с помощью pypy tweaked, чтобы использовать другой порядок при итерации элементов из dict; Я думаю, что наш код работает на pypy, хотя это не то, что мы когда-либо явно поддерживали. Однако, если какой-то эксперт pypy дает нам способ настроить порядок итераций словаря на разных прогонах, мы с этим будем работать.

4b9b3361

Ответ 1

Использование PyPy не лучший выбор здесь, учитывая, что он всегда сохраняет порядок вставки в своих dicts (с помощью метода, который заставляет dicts использовать меньше памяти). Разумеется, мы можем изменить его порядок, но он побеждает.

Вместо этого я предлагаю взломать исходный код CPython, чтобы изменить способ использования хеша внутри dictobject.c. Например, после каждого hash = PyObject_Hash(key); if (hash == -1) { ..error.. }; вы можете добавить hash ^= HASH_TWEAK; и скомпилировать разные версии CPython с разными значениями для HASH_TWEAK. (Я делал такую ​​вещь в какой-то момент, но я больше не могу ее найти. Вам нужно быть немного осторожным, где значения хэша являются исходными или модифицированными.)