【问题标题】:Unable to see or modify value of PYTHONHASHSEED through a module无法通过模块查看或修改 PYTHONHASHSEED 的值
【发布时间】:2015-09-12 12:25:55
【问题描述】:

尝试使用以下命令查看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 访问它?

【问题讨论】:

  • 您在 Bash shell 中从 printenv PYTHONHASHSEEDecho "$PYTHONHASHSEED" 得到什么输出?
  • @PM2Ring 我以前从未使用过我的 Bash shell。我假设我只是将它们粘贴到 PyCharm 的终端中。如果是这样,他们什么都不做(echo 只是创建一个空行)。
  • @PM2Ring 使用 "ctr+alt+T" 启动 Ubuntu 终端,我仍然得到相同的两个命令。分别没有结果和空行。
  • 我从您的聊天帖子中看到您想要运行具有各种 PYTHONHASHSEED 值的 Python 脚本。我将发布一些代码,展示一种简单的方法。

标签: python environment-variables python-3.4


【解决方案1】:

可以在 Python 脚本中设置 PYTHONHASHSEED,但它对 hash() 函数的行为没有影响 - 它需要在解释器启动之前在解释器的环境中设置.


如何使用纯 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

如何使用 Bash 设置其值

首先,我们有一个简短的 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

要运行这些程序,请将它们保存到同一个目录中,例如您运行 Python 脚本的常用目录。然后打开一个 Bash shell 并使用 cd 命令导航到该目录。

例如,如果您已将脚本保存到 /mnt/sda2/fred/python,那么您会这样做

cd /mnt/sda2/fred/python

接下来,使用此命令使pyhashtest.bsh 可执行:

chmod a+x pyhashtest.bsh

然后运行它

./pyhashtest.bsh

【讨论】:

  • 我正在尝试使用 dill 来散列函数。然而,它似乎受到这种随机化的影响。是否可以将此解决方案嵌入到我的散列函数中?我想需要选择要散列的函数,将其发送到新的解释器,然后再对其进行 unpickle 和 pickle。目前我正在对字节码进行哈希处理,但它似乎不太便携且速度慢得多。
  • @dawid 如果您有自己的哈希函数(或__hash__ 方法),您可以轻松绕过哈希随机化:只是不要直接在strbytes 上调用hash() .例如,将其拆分为一个元组,如下所示:hash(tuple(b'abc')).
  • @dawid 也许你应该问一个新问题,清楚地解释为什么你需要散列函数,以便读者了解生成的散列需要哪些属性。如果您认为它可以帮助读者理解您的问题,您可以链接回这个问题。或通过SO Python chatroom 讨论它。
  • 我正在散列函数以在运行和机器之间具有(概率上)唯一的确定性标识符。不幸的是,出于安全目的,PYTHONHASHSEED 会干扰泡菜/莳萝。这是我的问题:stackoverflow.com/questions/70129138/…
  • @dawid 我只是散列字节码(和函数的本地值),比如this。那应该是快速和便携的,但我不知道它是否适合你的用例。
【解决方案2】:

“哈希随机化默认开启”意味着(除其他外)即使没有PYTHONHASHSEED 环境变量,它也会开启 - 如果环境中未指定哈希种子,则随机选择一个.这个选择是在 python 内部完成的,os.environ 数组没有更新。

【讨论】:

  • 没错。当PYTHONHASHSEED 是随机的或未定义时,是否可以访问这个随机种子?
  • 我不知道,抱歉 - 事实上,我在寻找该确切问题的答案时发现了这篇 Stack Exchange 帖子。
  • 我通过 CPython 源代码挖掘了一下以寻找这个答案。它看起来没有暴露;它在 C 端的 PyInterpreterState 的核心配置中作为 hash_seed 隐藏。
  • 好的,所以应该可以编写一个 C 扩展模块来访问它。不过好像有点过分了……
猜你喜欢
  • 1970-01-01
  • 2017-01-09
  • 2022-01-21
  • 2013-01-12
  • 2014-04-01
  • 2021-04-29
  • 2017-08-12
  • 2019-07-10
  • 1970-01-01
相关资源
最近更新 更多