2015-09-12 2 views
3

Попытка увидеть значение PYTHONHASHSEED с помощью:Невозможно получить доступ к стоимости PYTHONHASHSEED через модуль

# (this is inside module_1.py) 
os.environ['PYTHONHASHSEED'] 

поднимает исключение KeyError:

Traceback (most recent call last): 
    File "/home/black/Dev/Projects/module_1.py", line 2, in <module> 
    os.environ['PYTHONHASHSEED'] 
    File "/usr/lib/python3.4/os.py", line 631, in __getitem__ 
    raise KeyError(key) from None 
KeyError: 'PYTHONHASHSEED' 

Печать содержимого os.environ по

for i in sorted(os.environ): 
    print(i) 

# prints: 
# CLUTTER_IM_MODULE 
# COMPIZ_BIN_PATH 
# ... 
# etc. 

показывает, что PYTHONHASHSEED не находится внутри, но я готов убедитесь, что он должен иметь значение с on Python 3.3 and greater, hash randomization is turned on by default.

Вопрос:
Почему я не могу получить доступ к его значение таким образом, и как я могу получить к нему доступ через module_1.py?

+0

Какие выходные вы получаете от 'printenv PYTHONHASHSEED' и' echo '$ PYTHONHASHSEED '' в вашей оболочке Bash? –

+0

@ PM2Ring Я никогда раньше не использовал свою оболочку Bash. Я предполагаю, что я просто вставляю их в терминал PyCharm. Если это так, они ничего не делают ('echo' просто создает пустую строку). –

+0

Нет, это команды оболочки, а не команды Python, поэтому вы должны запускать их в терминале, который может интерпретировать команды оболочки, а не в интерпретаторе Python. Я просто пытался установить, если PYTHONHASHSEED _really_ определен в вашей среде. Я подозреваю, что это не так, потому что команда Python 'os.environ ['PYTHONHASHSEED']' должна найти ее, если она есть. Но быстрая проверка через оболочку не повредит. Какую ОС вы используете? –

ответ

0

Вот короткая демонстрация установки PYTHONHASHSEED с использованием Bash. You может установить PYTHONHASHSEED в сценарии Python, но он не влияет на поведение функции hash() - он должен быть установлен в среде интерпретатора до запуска интерпретатора.

Во-первых, у нас есть короткий скрипт Bash pyhashtest.bsh, который использует переменную среды RANDOM в качестве семени для PYTHONHASHSEED. Эта переменная должна экспортироваться, чтобы интерпретатор Python мог ее видеть. Затем мы запускаем наш скрипт Python hashtest.py. Мы делаем это в цикле 5 раз, чтобы мы могли видеть, что использование разных семян влияет на значение хэша.

Сценарий Python hashtest.py читает PYTHONHASHSEED из среды и печатает его, чтобы показать, что он имеет значение, которое мы ожидаем от него. Затем мы вычисляем & печать хеша короткой строки.

pyhashtest.bsh

#!/usr/bin/env bash 

for((i=0; i<5; i++)); do 
    n=$RANDOM 
    echo "$i: Seed is $n" 
    export PYTHONHASHSEED="$n" 
    python hashtest.py 
    echo 
done 

hashtest.py

#!/usr/bin/env python 
import os 

s = 'abc' 
print('Hashseed is', os.environ['PYTHONHASHSEED']) 
print('hash of s is', hash(s)) 

типичный выход

0: Seed is 9352 
Hashseed is 9352 
hash of s is 401719638 

1: Seed is 24945 
Hashseed is 24945 
hash of s is -1250185385 

2: Seed is 17661 
Hashseed is 17661 
hash of s is -571990551 

3: Seed is 24313 
Hashseed is 24313 
hash of s is 99658978 

4: Seed is 21142 
Hashseed is 21142 
hash of s is -662114263 

Для запуска й ese, сохраните их оба в один и тот же каталог, например обычный каталог, из которого вы запускаете скрипты Python. Затем откройте оболочку Bash и перейдите к этому каталогу, используя команду cd.

Например, если вы сохранили сценарии /mnt/sda2/fred/python тогда вы могли бы сделать

cd /mnt/sda2/fred/python 

Далее сделайте pyhashtest.bsh исполняемый файл с помощью следующей команды:

chmod a+x pyhashtest.bsh 

Затем запустите его с

./pyhashtest.bsh 

Вот альтернативный, чистый подход Python. Хитрость заключается в передаче переменной среды интерпретатору Python в подпроцессе.

import random 
from subprocess import call 

random.seed(37) 
cmd = ['python', '-c', 'print(hash("abc"))'] 

for i in range(5): 
    hashseed = bytes(random.randint(0, 4294967295)) 
    print('\nhashseed', hashseed) 
    call(cmd, env={'PYTHONHASHSEED': hashseed}) 

выход

hashseed 2929187283 
-972692480 

hashseed 393430205 
2066796829 

hashseed 2653501013 
1620854360 

hashseed 3616018455 
-599248233 

hashseed 3584366196 
-2103216293 

Вы можете изменить cmd список таким образом, что он запускает hashtest.py выше скрипт:

cmd = ['python', 'hashtest.py'] 

или если hashtest.py является исполняемым,

cmd = './hashtest.py' 

Пройдя dict как аргумент env, мы заменим среду по умолчанию, которая будет передана команде. Если вам нужен доступ к этим другим переменным среды, вместо этого вы должны изменить os.environ в вызывающем скрипте, например, os.environ['PYTHONHASHSEED'] = hashseed.

+0

Ницца. Может ли 'pyhashtest.bsh' заменить на' .py', который использует 'subprocess.check_output ('the_pyhashtest_script_here')' для упрощения решения? –

+0

@ user536231: Конечно, вы можете использовать 'subprocess', но я не думаю, что добавление дополнительного слоя скриптов считается« упрощающим ». :) Я добавлю код в свой ответ, который показывает, как сделать такое тестирование исключительно на Python, без использования Bash. Но ИМХО - это хорошая идея, чтобы познакомиться с Bash, когда вы используете систему * nix. –

1

«хеш-рандомизация включена по умолчанию» означает, что она включена, даже если нет переменной среды PYTHONHASHSEED - если хеш-семя не указано в среде, выбирается случайным образом. Этот выбор выполняется внутри python, а массив os.environ не обновляется.

+0

Точно. Возможно ли получить доступ к этому случайному семени, если «PYTHONHASHSEED» является случайным или не определено? –

+1

Не знаю, извините - на самом деле я нашел этот пост в Stack Exchange, ища ответ на этот точный вопрос. – user7813790

+1

Я немного искал источник CPython в поисках этого ответа. Он не выглядит разоблаченным; он спрятан как «hash_seed» в конфигурации ядра PyInterpreterState на стороне C. –

Смежные вопросы