2015-06-01 2 views
18

Начиная с Python 3.3, алгоритм хеширования недетерминированно salted, чтобы избежать определенного вида атаки. Это удобно для веб-серверов, но при попытке отладки программы возникает боль: каждый раз, когда я запускаю свой скрипт, содержимое dict повторяется в другом порядке.Отключить хеш-рандомизацию изнутри программы python

Некоторые ранние версии питона имели -R флаг позволяющий хэш рандомизации, но теперь, когда это поведение по умолчанию, флаг не был заменен на свою противоположность. рандомизация может быть отключена путем установки переменной окружения PYTHONHASHSEED:

PYTHONHASHSEED

Если эта переменная не установлена ​​или установлена ​​на случайное, случайное значение используется для семян хэши, ул байтов и datetime.
Если значение PYTHONHASHSEED равно целочисленному значению, оно используется как фиксированное семя для генерации хеша() типов, охватываемых хэш-рандомизацией.

Уловка заключается в том, что эта переменная должна быть установлена ​​перед запуском процесса python. Я попытался установить его с помощью os.putenv() или в os.environ, но они, похоже, не влияют на метод хэширования. Это не слишком удивительно: я бы не ожидал, что python проверит среду перед каждым набором или поиском словаря! Итак, остается вопрос:

Есть ли способ для программы python отключить собственную хэш-рандомизацию?

+0

Это должно произойти, прежде чем любой фактический код Python выполняется; к тому времени слишком много строк были хэшированы и помещены в такие вещи, как тип и модуль '__dict__'s. – user2357112

+0

Я думал то же самое; но я надеюсь, что кто-то, кто знает больше, может прокомментировать. – alexis

+0

Это соответствующие коммиты: [f4b7ecf8a5f8] (https://hg.python.org/cpython/rev/f4b7ecf8a5f8) и [6b7704fe1be1] (https://hg.python.org/cpython/rev/6b7704fe1be1) - взгляд через него я не сразу вижу решение, но это отправная точка. – dimo414

ответ

11

Подозреваю, что это невозможно, к сожалению. Глядя на test_hash.py класс HashRandomizationTests и его потомки были добавлены в commit that introduced this behavior. Они проверяют поведение хеширования, изменяя среду и запуская новый процесс с явно установленным PYTHONHASHSEED. Возможно, вы могли бы попытаться скопировать этот шаблон.

я только заметил, что ты сказал «Каждый раз, когда я бегу мой сценарий, содержание Dict повторяются в другом порядке». - Я полагаю, что вы знаете о collections.OrderedDict, верно? Это нормальный способ получить надежную итерацию хэширования.


Если вы готовы установить значение в среде оболочки, вы также можете просто обернуть питона вызов в Баш скрипт, например,

#! /bin/bash 
export PYTHONHASHSEED=0 

# call your python program here 

Это позволяет избежать необходимости управлять всей средой, до тех пор, пока вы хорошо с сценарии оболочки.

Или даже просто передать значение в командной строке:

$ PYTHONHASHSEED=0 python YOURSCRIPT.py 
+1

Спасибо, это довольно сильное указание.И хороший совет для возрождения - хотя и за пределами уродства, есть контексты, где это не практично (например, при работе в ноутбуке ipython, обслуживаемом удаленным «ядром»). Наверное, я могу просто установить его для входа в мою среду ... Я сам не буду делать сам. – alexis