21

我正在尝试使用 python 创建一个随机二进制文件。这是我已经得到的:

f = open(filename,'wb')
for i in xrange(size_kb):
    for ii in xrange(1024/4):
        f.write(struct.pack("=I",random.randint(0,sys.maxint*2+1)))

f.close()

但它非常慢(在我的 3.9GHz SSD 磁盘机器上 size_kb=1024 为 0.82 秒)。一个很大的瓶颈似乎是随机 int 生成(用 0 替换 randint() 将运行时间从 0.82 秒减少到 0.14 秒)。

现在我知道有更有效的方法来创建随机数据文件(即 dd if=/dev/urandom),但出于好奇,我正在尝试解决这个问题……有没有明显的改进方法?

4

2 回答 2

51

恕我直言 - 以下是完全多余的:

f.write(struct.pack("=I",random.randint(0,sys.maxint*2+1)))

绝对没有必要使用struct.pack,只需执行以下操作:

import os

with open('output_file', 'wb') as fout:
    fout.write(os.urandom(1024)) # replace 1024 with size_kb if not unreasonably large

然后,如果您需要重新使用该文件来读取整数,struct.unpack那么。

(我的用例是为单元测试生成一个文件,所以我只需要一个与其他生成的文件不同的文件)。

另一种选择是将 UUID4 写入文件,但由于我不知道确切的用例,我不确定这是否可行。

于 2013-01-11T10:43:35.640 回答
3

您应该编写的 python 代码完全取决于您打算使用随机二进制文件的方式。如果您只需要一个“相当好的”随机性用于多种用途,那么 Jon Clements 的代码可能是最好的。

但是,至少在 Linux 操作系统上,os.urandom 依赖于 /dev/urandom,Linux 内核 (drivers/char/random.c) 中对此进行了如下描述:

/dev/urandom 设备 [...] 将返回请求的字节数。随着越来越多的随机字节被请求,而没有给熵池充值的时间,这将导致随机数仅具有加密强度。然而,对于许多应用来说,这是可以接受的。

所以问题是,这对您的应用程序是否可以接受?如果您更喜欢更安全的 RNG,则可以改为读取 /dev/random 上的字节。该设备的主要不便之处:如果 Linux 内核无法收集足够的熵,它可能会无限期地阻塞。还有其他加密安全的 RNG,例如EGD

或者,如果您主要关心的是执行速度,并且如果您只需要蒙特卡洛方法的一些“轻微随机性”(即不可预测性无关紧要,均匀分布确实如此),您可以考虑生成一次随机二进制文件并使用它很多次,至少对于发展。

于 2013-01-11T11:21:10.310 回答