如何使用Python从/ dev / random获取数字?

时间:2013-02-06 02:52:51

标签: python

我正在尝试编写一个python脚本来测试/ dev / random的随机性,但我不能让它给我任何数字。我的代码看起来像这样

以open(“/ dev / random”,“rb”)作为文件:      print f.read(10)

我认为应该从/ dev / random打印出10个字节,但不是数字,而是打印出奇怪的字符(非标准字母,没有数字)。知道我做错了吗?

谢谢!

4 个答案:

答案 0 :(得分:10)

Python有一个内置函数(也可以在其他操作系统上使用适当的方法)...

import os
print os.urandom(10)
# '\xf1\x11xJOl\xab\xcc\xf0\xfd'

来自http://docs.python.org/2/library/os.html#os.urandom

的文档
  

此函数返回来自OS特定随机源的随机字节。对于加密应用程序,返回的数据应该是不可预测的,尽管其确切的质量取决于操作系统的实现。在类UNIX系统上,这将查询/ dev / urandom,在Windows上,它将使用CryptGenRandom。如果未找到随机源,则将引发NotImplementedError。

如果您希望这些字节为数字,则可以通过以下方式进行转换:

>>> rand = os.urandom(10)
>>> int(rand.encode('hex'), 16)
1138412584848598544216317L

虽然/dev/random/dev/urandom略有不同,但您可以使用现有的.read()操作,只需对int转换,如果差异对您很重要。

答案 1 :(得分:9)

你得到10个字节。 Python不会自动将它们变成数字。

我建议您以4的倍数获取字节,然后将它们转换为32位无符号整数,然后将它们缩放到您需要的任何值。

编辑:旧代码显示了这个想法,但很少分为功能。这是相同的基本想法,但现在可以方便地打包成函数。

import os
import struct

_random_source = open("/dev/random", "rb")

def random_bytes(len):
    return _random_source.read(len)

def unpack_uint32(bytes):
    tup = struct.unpack("I", bytes)
    return tup[0]

UINT32_MAX = 0xffffffff
def randint(low, high):
    """
    Return a random integer in the range [low, high], including
    both endpoints.
    """
    n = (high - low) + 1
    assert n >= 1
    scale_factor = n / float(UINT32_MAX + 1)
    random_uint32 = unpack_uint32(random_bytes(4))
    result = int(scale_factor * random_uint32) + low
    return result

def randint_gen(low, high, count):
    """
    Generator that yields random integers in the range [low, high],
    including both endpoints.
    """
    n = (high - low) + 1
    assert n >= 1
    scale_factor = n / float(UINT32_MAX + 1)
    for _ in range(count):
        random_uint32 = unpack_uint32(random_bytes(4))
        result = int(scale_factor * random_uint32) + low
        yield result

if __name__ == "__main__":
    # roll 3 dice individually with randint()
    result = [randint(1, 6) for _ in range(3)]
    print(result)

    # roll 3 dice more efficiently with randint_gen()
    print(list(randint_gen(1, 6, 3)))

答案 2 :(得分:1)

它打印随机字符,因此只需使用ord()函数将它们转换为int。类似的东西:

with open("/dev/random", 'rb') as file: print [ord(x) for x in file.read(10)]

这将打印一个从0到255的10个随机整数的列表。(我得到了:[117, 211, 225, 24, 134, 145, 51, 234, 153, 89])。

答案 3 :(得分:0)

在Python 3.2及更高版本中,以下内容比旧答案中的解决方案更短,可能更快:

with open("/dev/random", 'rb') as f:
    print(int.from_bytes(f.read(10), 'big'))

这会打印一个80位数字(范围为0到2 ^ 80-1)。